Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: infinite ping - concurent calls #93

Merged
merged 6 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Install dependencies
run: go get .
- name: Run tests
run: go test ./... -v
run: go test ./... -v -timeout 30s
- name: Build
run: go build -o bin/
- name: Test windows cmd
Expand Down
27 changes: 13 additions & 14 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,27 @@ func (r *Root) updateContext(cmd string, args []string) error {
return nil
}

func createLocations(from string) ([]globalping.Locations, bool, error) {
fromArr := strings.Split(from, ",")
func (r *Root) getLocations() ([]globalping.Locations, error) {
fromArr := strings.Split(r.ctx.From, ",")
if len(fromArr) == 1 {
mId, err := mapFromHistory(fromArr[0])
mId, err := mapFromSession(fromArr[0])
if err != nil {
return nil, false, err
return nil, err
}
isFromHistory := false
if mId == "" {
mId = strings.TrimSpace(fromArr[0])
} else {
isFromHistory = true
r.ctx.RecordToSession = false
}
return []globalping.Locations{{Magic: mId}}, isFromHistory, nil
return []globalping.Locations{{Magic: mId}}, nil
}
locations := make([]globalping.Locations, len(fromArr))
for i, v := range fromArr {
locations[i] = globalping.Locations{
Magic: strings.TrimSpace(v),
}
}
return locations, false, nil
return locations, nil
}

type TargetQuery struct {
Expand Down Expand Up @@ -155,7 +154,7 @@ func findAndRemoveResolver(args []string) (string, []string) {
}

// Maps a location to a measurement ID from history, if possible.
func mapFromHistory(location string) (string, error) {
func mapFromSession(location string) (string, error) {
if location == "" {
return "", nil
}
Expand All @@ -164,19 +163,19 @@ func mapFromHistory(location string) (string, error) {
if err != nil {
return "", ErrInvalidIndex
}
return getIdFromHistory(index)
return getIdFromSession(index)
}
if location == "first" {
return getIdFromHistory(1)
return getIdFromSession(1)
}
if location == "last" || location == "previous" {
return getIdFromHistory(-1)
return getIdFromSession(-1)
}
return "", nil
}

// Returns the measurement ID at the given index from the session history
func getIdFromHistory(index int) (string, error) {
func getIdFromSession(index int) (string, error) {
if index == 0 {
return "", ErrInvalidIndex
}
Expand Down Expand Up @@ -227,7 +226,7 @@ func getIdFromHistory(index int) (string, error) {
}

// Saves the measurement ID to the session history
func saveIdToHistory(id string) error {
func saveIdToSession(id string) error {
_, err := os.Stat(getSessionPath())
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
Expand Down
192 changes: 0 additions & 192 deletions cmd/common_test.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,13 @@
package cmd

import (
"errors"
"io/fs"
"os"
"testing"
"time"

"github.com/jsdelivr/globalping-cli/globalping"
"github.com/jsdelivr/globalping-cli/view"
"github.com/stretchr/testify/assert"
)

var (
measurementID1 = "WOOxHNyhdsBQYEjU"
measurementID2 = "hhUicONd75250Z1b"
measurementID3 = "YPDXL29YeGctf6iJ"
measurementID4 = "hH3tBVPZEj5k6AcW"

defaultCurrentTime = time.Unix(0, 0)
)

func Test_UpdateContext(t *testing.T) {
for scenario, fn := range map[string]func(t *testing.T){
"no_arg": test_updateContext_NoArg,
Expand Down Expand Up @@ -181,182 +168,3 @@ func Test_FindAndRemoveResolver_ResolverOnly(t *testing.T) {
assert.Equal(t, "1.1.1.1", resolver)
assert.Equal(t, []string{"example.com"}, argsWithoutResolver)
}

func Test_CreateLocations(t *testing.T) {
for scenario, fn := range map[string]func(t *testing.T){
"valid_single": test_CreateLocations_Single,
"valid_multiple": test_CreateLocations_Multiple,
"valid_multiple_whitespace": test_CreateLocations_Multiple_Whitespace,
"valid_session_last_measurement": test_CreateLocations_Session_Last_Measurement,
"valid_session_first_measurement": test_CreateLocations_Session_First_Measurement,
"valid_session_measurement_at_index": test_CreateLocations_Session_Measurement_At_Index,
"valid_session_no_session": test_CreateLocations_Session_No_Session,
"invalid_session_index": test_CreateLocations_Session_Invalid_Index,
} {
t.Run(scenario, func(t *testing.T) {
fn(t)
t.Cleanup(sessionCleanup)
})
}
}

func test_CreateLocations_Single(t *testing.T) {
locations, isPreviousMeasurementId, err := createLocations("New York")
assert.Equal(t, []globalping.Locations{{Magic: "New York"}}, locations)
assert.False(t, isPreviousMeasurementId)
assert.Nil(t, err)
}

func test_CreateLocations_Multiple(t *testing.T) {
locations, isPreviousMeasurementId, err := createLocations("New York,Los Angeles")
assert.Equal(t, []globalping.Locations{{Magic: "New York"}, {Magic: "Los Angeles"}}, locations)
assert.False(t, isPreviousMeasurementId)
assert.Nil(t, err)
}

func test_CreateLocations_Multiple_Whitespace(t *testing.T) {
locations, isPreviousMeasurementId, err := createLocations("New York, Los Angeles ")
assert.Equal(t, []globalping.Locations{{Magic: "New York"}, {Magic: "Los Angeles"}}, locations)
assert.False(t, isPreviousMeasurementId)
assert.Nil(t, err)
}

func test_CreateLocations_Session_Last_Measurement(t *testing.T) {
_ = saveIdToHistory(measurementID1)
locations, isPreviousMeasurementId, err := createLocations("@1")
assert.Equal(t, []globalping.Locations{{Magic: measurementID1}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)

locations, isPreviousMeasurementId, err = createLocations("last")
assert.Equal(t, []globalping.Locations{{Magic: measurementID1}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)

locations, isPreviousMeasurementId, err = createLocations("previous")
assert.Equal(t, []globalping.Locations{{Magic: measurementID1}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)
}

func test_CreateLocations_Session_First_Measurement(t *testing.T) {
_ = saveIdToHistory(measurementID1)
_ = saveIdToHistory(measurementID2)
locations, isPreviousMeasurementId, err := createLocations("@-1")
assert.Equal(t, []globalping.Locations{{Magic: measurementID2}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)

locations, isPreviousMeasurementId, err = createLocations("last")
assert.Equal(t, []globalping.Locations{{Magic: measurementID2}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)
}

func test_CreateLocations_Session_Measurement_At_Index(t *testing.T) {
_ = saveIdToHistory(measurementID1)
_ = saveIdToHistory(measurementID2)
_ = saveIdToHistory(measurementID3)
_ = saveIdToHistory(measurementID4)
locations, isPreviousMeasurementId, err := createLocations("@2")
assert.Equal(t, []globalping.Locations{{Magic: measurementID2}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)

locations, isPreviousMeasurementId, err = createLocations("@-2")
assert.Equal(t, []globalping.Locations{{Magic: measurementID3}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)

locations, isPreviousMeasurementId, err = createLocations("@-4")
assert.Equal(t, []globalping.Locations{{Magic: measurementID1}}, locations)
assert.True(t, isPreviousMeasurementId)
assert.Nil(t, err)
}

func test_CreateLocations_Session_No_Session(t *testing.T) {
locations, isPreviousMeasurementId, err := createLocations("@1")
assert.Nil(t, locations)
assert.False(t, isPreviousMeasurementId)
assert.Equal(t, ErrorNoPreviousMeasurements, err)
}

func test_CreateLocations_Session_Invalid_Index(t *testing.T) {
locations, isPreviousMeasurementId, err := createLocations("@0")
assert.Nil(t, locations)
assert.False(t, isPreviousMeasurementId)
assert.Equal(t, ErrInvalidIndex, err)

locations, isPreviousMeasurementId, err = createLocations("@")
assert.Nil(t, locations)
assert.False(t, isPreviousMeasurementId)
assert.Equal(t, ErrInvalidIndex, err)

locations, isPreviousMeasurementId, err = createLocations("@x")
assert.Nil(t, locations)
assert.False(t, isPreviousMeasurementId)
assert.Equal(t, ErrInvalidIndex, err)

_ = saveIdToHistory(measurementID1)
locations, isPreviousMeasurementId, err = createLocations("@2")
assert.Nil(t, locations)
assert.False(t, isPreviousMeasurementId)
assert.Equal(t, ErrIndexOutOfRange, err)

locations, isPreviousMeasurementId, err = createLocations("@-2")
assert.Nil(t, locations)
assert.False(t, isPreviousMeasurementId)
assert.Equal(t, ErrIndexOutOfRange, err)
}

func Test_SaveMeasurementID(t *testing.T) {
for scenario, fn := range map[string]func(t *testing.T){
"valid_new_session": test_SaveMeasurementID_New_Session,
"valid_existing_session": test_SaveMeasurementID_Existing_Session,
} {
t.Run(scenario, func(t *testing.T) {
fn(t)
t.Cleanup(sessionCleanup)
})
}
}

func test_SaveMeasurementID_New_Session(t *testing.T) {
_ = saveIdToHistory(measurementID1)
assert.FileExists(t, getMeasurementsPath())
b, err := os.ReadFile(getMeasurementsPath())
assert.NoError(t, err)
expected := []byte(measurementID1 + "\n")
assert.Equal(t, expected, b)
}

func test_SaveMeasurementID_Existing_Session(t *testing.T) {
err := os.Mkdir(getSessionPath(), 0755)
if err != nil {
t.Fatalf("Failed to create session path: %s", err)
}
err = os.WriteFile(getMeasurementsPath(), []byte(measurementID1+"\n"), 0644)
if err != nil {
t.Fatalf("Failed to create measurements file: %s", err)
}
_ = saveIdToHistory(measurementID2)
b, err := os.ReadFile(getMeasurementsPath())
assert.NoError(t, err)
expected := []byte(measurementID1 + "\n" + measurementID2 + "\n")
assert.Equal(t, expected, b)
}

func sessionCleanup() {
sessionPath := getSessionPath()
err := os.RemoveAll(sessionPath)
if err != nil && !errors.Is(err, fs.ErrNotExist) {
panic("Failed to remove session path: " + err.Error())
}
}

func getMeasurementCreateResponse(id string) *globalping.MeasurementCreateResponse {
return &globalping.MeasurementCreateResponse{
ID: id,
ProbesCount: 1,
}
}
13 changes: 8 additions & 5 deletions cmd/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ func (r *Root) RunDNS(cmd *cobra.Command, args []string) error {
return err
}

r.ctx.RecordToSession = true

opts := &globalping.MeasurementCreate{
Type: "dns",
Target: r.ctx.Target,
Expand All @@ -83,8 +85,7 @@ func (r *Root) RunDNS(cmd *cobra.Command, args []string) error {
Trace: r.ctx.Trace,
},
}
isPreviousMeasurementId := false
opts.Locations, isPreviousMeasurementId, err = createLocations(r.ctx.From)
opts.Locations, err = r.getLocations()
if err != nil {
cmd.SilenceUsage = true
return err
Expand All @@ -98,9 +99,11 @@ func (r *Root) RunDNS(cmd *cobra.Command, args []string) error {
return err
}

// Save measurement ID to history
if !isPreviousMeasurementId {
err := saveIdToHistory(res.ID)
r.ctx.MeasurementsCreated++

if r.ctx.RecordToSession {
r.ctx.RecordToSession = false
err := saveIdToSession(res.ID)
if err != nil {
r.printer.Printf("Warning: %s\n", err)
}
Expand Down
Loading