Skip to content

Commit

Permalink
feat: infinite ping - concurent calls (jsdelivr#93)
Browse files Browse the repository at this point in the history
* Refactoring

* Concurent calls

* Update concurent logic, add tests

* Skip tests on windows

* Update sleep times

* windows
  • Loading branch information
radulucut authored Mar 18, 2024
1 parent d265e50 commit 52b7a42
Show file tree
Hide file tree
Showing 31 changed files with 1,621 additions and 1,553 deletions.
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

0 comments on commit 52b7a42

Please sign in to comment.