-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(webconnectivitylte): include network events (#1503)
While there, notice that we can increase the coverage in webconnectivityqa. Closes ooni/probe#2674
- Loading branch information
1 parent
912c3e6
commit 4439cbd
Showing
29 changed files
with
512 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package webconnectivityqa | ||
|
||
import ( | ||
"errors" | ||
"strings" | ||
|
||
"github.com/ooni/probe-cli/v3/internal/model" | ||
"github.com/ooni/probe-cli/v3/internal/must" | ||
"github.com/ooni/probe-cli/v3/internal/netxlite" | ||
"github.com/ooni/probe-cli/v3/internal/x/dslx" | ||
) | ||
|
||
// Checker checks whether a measurement is correct. | ||
type Checker interface { | ||
Check(mx *model.Measurement) error | ||
} | ||
|
||
// ReadWriteEventsExistentialChecker fails if there are zero network events. | ||
type ReadWriteEventsExistentialChecker struct{} | ||
|
||
var _ Checker = &ReadWriteEventsExistentialChecker{} | ||
|
||
// ErrCheckerNoReadWriteEvents indicates that a checker did not find any read/write events. | ||
var ErrCheckerNoReadWriteEvents = errors.New("no read or write events") | ||
|
||
// ErrCheckerUnexpectedWebConnectivityVersion indicates that the version is unexpected | ||
var ErrCheckerUnexpectedWebConnectivityVersion = errors.New("unexpected Web Connectivity version") | ||
|
||
// Check implements Checker. | ||
func (*ReadWriteEventsExistentialChecker) Check(mx *model.Measurement) error { | ||
// we don't care about v0.4 | ||
if strings.HasPrefix(mx.TestVersion, "0.4.") { | ||
return nil | ||
} | ||
|
||
// make sure it's v0.5 | ||
if !strings.HasPrefix(mx.TestVersion, "0.5.") { | ||
return ErrCheckerUnexpectedWebConnectivityVersion | ||
} | ||
|
||
// serialize and reparse the test keys | ||
var tk *dslx.Observations | ||
must.UnmarshalJSON(must.MarshalJSON(mx.TestKeys), &tk) | ||
|
||
// count the read/write events | ||
var count int | ||
for _, ev := range tk.NetworkEvents { | ||
switch ev.Operation { | ||
case netxlite.ReadOperation, netxlite.WriteOperation: | ||
count++ | ||
default: | ||
// nothing | ||
} | ||
} | ||
|
||
// make sure there's at least one network event | ||
if count <= 0 { | ||
return ErrCheckerNoReadWriteEvents | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package webconnectivityqa_test | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"testing" | ||
|
||
"github.com/ooni/probe-cli/v3/internal/experiment/webconnectivitylte" | ||
"github.com/ooni/probe-cli/v3/internal/mocks" | ||
"github.com/ooni/probe-cli/v3/internal/model" | ||
"github.com/ooni/probe-cli/v3/internal/must" | ||
"github.com/ooni/probe-cli/v3/internal/optional" | ||
"github.com/ooni/probe-cli/v3/internal/webconnectivityqa" | ||
) | ||
|
||
func TestConfigureCustomCheckers(t *testing.T) { | ||
tc := &webconnectivityqa.TestCase{ | ||
Name: "", | ||
Input: "", | ||
ExpectErr: false, | ||
ExpectTestKeys: &webconnectivityqa.TestKeys{ | ||
Accessible: true, | ||
Blocking: nil, | ||
}, | ||
Checkers: []webconnectivityqa.Checker{&webconnectivityqa.ReadWriteEventsExistentialChecker{}}, | ||
} | ||
measurer := &mocks.ExperimentMeasurer{ | ||
MockExperimentName: func() string { | ||
return "web_connectivity" | ||
}, | ||
MockExperimentVersion: func() string { | ||
return "0.5.28" | ||
}, | ||
MockRun: func(ctx context.Context, args *model.ExperimentArgs) error { | ||
args.Measurement.TestKeys = &webconnectivitylte.TestKeys{ | ||
Accessible: optional.Some(true), | ||
Blocking: nil, | ||
} | ||
return nil | ||
}, | ||
} | ||
err := webconnectivityqa.RunTestCase(measurer, tc) | ||
if !errors.Is(err, webconnectivityqa.ErrCheckerNoReadWriteEvents) { | ||
t.Fatal("unexpected error", err) | ||
} | ||
} | ||
|
||
func TestReadWriteEventsExistentialChecker(t *testing.T) { | ||
type testcase struct { | ||
name string | ||
version string | ||
tk string | ||
expect error | ||
} | ||
|
||
cases := []testcase{{ | ||
name: "with Web Connectivity v0.4", | ||
version: "0.4.3", | ||
tk: `{}`, | ||
expect: nil, | ||
}, { | ||
name: "with Web Connectivity v0.6", | ||
version: "0.6.0", | ||
tk: `{}`, | ||
expect: webconnectivityqa.ErrCheckerUnexpectedWebConnectivityVersion, | ||
}, { | ||
name: "with read/write network events", | ||
version: "0.5.28", | ||
tk: `{"network_events":[{"operation":"read"},{"operation":"write"}]}`, | ||
expect: nil, | ||
}, { | ||
name: "without network events", | ||
version: "0.5.28", | ||
tk: `{"network_events":[]}`, | ||
expect: webconnectivityqa.ErrCheckerNoReadWriteEvents, | ||
}, { | ||
name: "with no read/write network events", | ||
version: "0.5.28", | ||
tk: `{"network_events":[{"operation":"connect"},{"operation":"close"}]}`, | ||
expect: webconnectivityqa.ErrCheckerNoReadWriteEvents, | ||
}} | ||
|
||
for _, tc := range cases { | ||
t.Run(tc.name, func(t *testing.T) { | ||
var tks map[string]any | ||
must.UnmarshalJSON([]byte(tc.tk), &tks) | ||
|
||
meas := &model.Measurement{ | ||
TestKeys: tks, | ||
TestVersion: tc.version, | ||
} | ||
|
||
err := (&webconnectivityqa.ReadWriteEventsExistentialChecker{}).Check(meas) | ||
|
||
switch { | ||
case tc.expect == nil && err == nil: | ||
return | ||
|
||
case tc.expect == nil && err != nil: | ||
t.Fatal("expected", tc.expect, "got", err) | ||
|
||
case tc.expect != nil && err == nil: | ||
t.Fatal("expected", tc.expect, "got", err) | ||
|
||
case tc.expect != nil && err != nil: | ||
if err.Error() != tc.expect.Error() { | ||
t.Fatal("expected", tc.expect, "got", err) | ||
} | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.