refactor: remove model.ExperimentOrchestraClient (#284)
* ongoing * while there, make sure we test everything * reorganize previous commit * ensure we have reasonable coverage in session The code in here would be better with unit tests. We have too many integration tests and the tests overall are too slow. But it's also true that I should not write a giant diff as part of this PR.
This commit is contained in:
parent
4700ba791d
commit
79e8424677
|
@ -55,6 +55,11 @@ type TargetResults struct {
|
||||||
TargetSource string `json:"target_source,omitempty"`
|
TargetSource string `json:"target_source,omitempty"`
|
||||||
TCPConnect oonidatamodel.TCPConnectList `json:"tcp_connect"`
|
TCPConnect oonidatamodel.TCPConnectList `json:"tcp_connect"`
|
||||||
TLSHandshakes oonidatamodel.TLSHandshakesList `json:"tls_handshakes"`
|
TLSHandshakes oonidatamodel.TLSHandshakesList `json:"tls_handshakes"`
|
||||||
|
|
||||||
|
// Only for testing. We don't care about this field otherwise. We
|
||||||
|
// cannot make this private because otherwise the IP address sanitizer
|
||||||
|
// is going to panic over a private field.
|
||||||
|
DirPortCount int `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerExtensions(m *model.Measurement) {
|
func registerExtensions(m *model.Measurement) {
|
||||||
|
@ -78,6 +83,7 @@ func (tr *TargetResults) fillSummary() {
|
||||||
case "dir_port":
|
case "dir_port":
|
||||||
// The UI currently doesn't care about this protocol
|
// The UI currently doesn't care about this protocol
|
||||||
// as long as drawing a table is concerned.
|
// as long as drawing a table is concerned.
|
||||||
|
tr.DirPortCount++
|
||||||
case "obfs4":
|
case "obfs4":
|
||||||
// We currently only perform an OBFS4 handshake, hence
|
// We currently only perform an OBFS4 handshake, hence
|
||||||
// the final Failure is the handshake result
|
// the final Failure is the handshake result
|
||||||
|
@ -136,20 +142,16 @@ func (tk *TestKeys) fillToplevelKeys() {
|
||||||
|
|
||||||
// Measurer performs the measurement.
|
// Measurer performs the measurement.
|
||||||
type Measurer struct {
|
type Measurer struct {
|
||||||
config Config
|
config Config
|
||||||
fetchTorTargets func(ctx context.Context, clnt model.ExperimentOrchestraClient, cc string) (map[string]model.TorTarget, error)
|
fetchTorTargets func(ctx context.Context, sess model.ExperimentSession, cc string) (map[string]model.TorTarget, error)
|
||||||
newOrchestraClient func(ctx context.Context, sess model.ExperimentSession) (model.ExperimentOrchestraClient, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMeasurer creates a new Measurer
|
// NewMeasurer creates a new Measurer
|
||||||
func NewMeasurer(config Config) *Measurer {
|
func NewMeasurer(config Config) *Measurer {
|
||||||
return &Measurer{
|
return &Measurer{
|
||||||
config: config,
|
config: config,
|
||||||
fetchTorTargets: func(ctx context.Context, clnt model.ExperimentOrchestraClient, cc string) (map[string]model.TorTarget, error) {
|
fetchTorTargets: func(ctx context.Context, sess model.ExperimentSession, cc string) (map[string]model.TorTarget, error) {
|
||||||
return clnt.FetchTorTargets(ctx, cc)
|
return sess.FetchTorTargets(ctx, cc)
|
||||||
},
|
|
||||||
newOrchestraClient: func(ctx context.Context, sess model.ExperimentSession) (model.ExperimentOrchestraClient, error) {
|
|
||||||
return sess.NewOrchestraClient(ctx)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,11 +191,7 @@ func (m *Measurer) gimmeTargets(
|
||||||
) (map[string]model.TorTarget, error) {
|
) (map[string]model.TorTarget, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
clnt, err := m.newOrchestraClient(ctx, sess)
|
return m.fetchTorTargets(ctx, sess, sess.ProbeCC())
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return m.fetchTorTargets(ctx, clnt, sess.ProbeCC())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// keytarget contains a key and the related target
|
// keytarget contains a key and the related target
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/legacy/oonitemplates"
|
"github.com/ooni/probe-cli/v3/internal/engine/legacy/oonitemplates"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/errorx"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/probeservices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewExperimentMeasurer(t *testing.T) {
|
func TestNewExperimentMeasurer(t *testing.T) {
|
||||||
|
@ -31,32 +30,10 @@ func TestNewExperimentMeasurer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMeasurerMeasureNewOrchestraClientError(t *testing.T) {
|
|
||||||
measurer := NewMeasurer(Config{})
|
|
||||||
expected := errors.New("mocked error")
|
|
||||||
measurer.newOrchestraClient = func(ctx context.Context, sess model.ExperimentSession) (model.ExperimentOrchestraClient, error) {
|
|
||||||
return nil, expected
|
|
||||||
}
|
|
||||||
err := measurer.Run(
|
|
||||||
context.Background(),
|
|
||||||
&mockable.Session{
|
|
||||||
MockableLogger: log.Log,
|
|
||||||
},
|
|
||||||
new(model.Measurement),
|
|
||||||
model.NewPrinterCallbacks(log.Log),
|
|
||||||
)
|
|
||||||
if !errors.Is(err, expected) {
|
|
||||||
t.Fatal("not the error we expected")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMeasurerMeasureFetchTorTargetsError(t *testing.T) {
|
func TestMeasurerMeasureFetchTorTargetsError(t *testing.T) {
|
||||||
measurer := NewMeasurer(Config{})
|
measurer := NewMeasurer(Config{})
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
measurer.newOrchestraClient = func(ctx context.Context, sess model.ExperimentSession) (model.ExperimentOrchestraClient, error) {
|
measurer.fetchTorTargets = func(ctx context.Context, sess model.ExperimentSession, cc string) (map[string]model.TorTarget, error) {
|
||||||
return new(probeservices.Client), nil
|
|
||||||
}
|
|
||||||
measurer.fetchTorTargets = func(ctx context.Context, clnt model.ExperimentOrchestraClient, cc string) (map[string]model.TorTarget, error) {
|
|
||||||
return nil, expected
|
return nil, expected
|
||||||
}
|
}
|
||||||
err := measurer.Run(
|
err := measurer.Run(
|
||||||
|
@ -74,10 +51,7 @@ func TestMeasurerMeasureFetchTorTargetsError(t *testing.T) {
|
||||||
|
|
||||||
func TestMeasurerMeasureFetchTorTargetsEmptyList(t *testing.T) {
|
func TestMeasurerMeasureFetchTorTargetsEmptyList(t *testing.T) {
|
||||||
measurer := NewMeasurer(Config{})
|
measurer := NewMeasurer(Config{})
|
||||||
measurer.newOrchestraClient = func(ctx context.Context, sess model.ExperimentSession) (model.ExperimentOrchestraClient, error) {
|
measurer.fetchTorTargets = func(ctx context.Context, sess model.ExperimentSession, cc string) (map[string]model.TorTarget, error) {
|
||||||
return new(probeservices.Client), nil
|
|
||||||
}
|
|
||||||
measurer.fetchTorTargets = func(ctx context.Context, clnt model.ExperimentOrchestraClient, cc string) (map[string]model.TorTarget, error) {
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
measurement := new(model.Measurement)
|
measurement := new(model.Measurement)
|
||||||
|
@ -102,10 +76,7 @@ func TestMeasurerMeasureGoodWithMockedOrchestra(t *testing.T) {
|
||||||
// This test mocks orchestra to return a nil list of targets, so the code runs
|
// This test mocks orchestra to return a nil list of targets, so the code runs
|
||||||
// but we don't perform any actual network actions.
|
// but we don't perform any actual network actions.
|
||||||
measurer := NewMeasurer(Config{})
|
measurer := NewMeasurer(Config{})
|
||||||
measurer.newOrchestraClient = func(ctx context.Context, sess model.ExperimentSession) (model.ExperimentOrchestraClient, error) {
|
measurer.fetchTorTargets = func(ctx context.Context, sess model.ExperimentSession, cc string) (map[string]model.TorTarget, error) {
|
||||||
return new(probeservices.Client), nil
|
|
||||||
}
|
|
||||||
measurer.fetchTorTargets = func(ctx context.Context, clnt model.ExperimentOrchestraClient, cc string) (map[string]model.TorTarget, error) {
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
err := measurer.Run(
|
err := measurer.Run(
|
||||||
|
@ -167,10 +138,8 @@ func TestMeasurerMeasureSanitiseOutput(t *testing.T) {
|
||||||
measurer := NewMeasurer(Config{})
|
measurer := NewMeasurer(Config{})
|
||||||
sess := newsession()
|
sess := newsession()
|
||||||
key := "xyz-xyz-xyz-theCh2ju-ahG4chei-Ai2eka0a"
|
key := "xyz-xyz-xyz-theCh2ju-ahG4chei-Ai2eka0a"
|
||||||
sess.MockableOrchestraClient = &mockable.ExperimentOrchestraClient{
|
sess.MockableFetchTorTargetsResult = map[string]model.TorTarget{
|
||||||
MockableFetchTorTargetsResult: map[string]model.TorTarget{
|
key: staticPrivateTestingTarget,
|
||||||
key: staticPrivateTestingTarget,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
measurement := new(model.Measurement)
|
measurement := new(model.Measurement)
|
||||||
err := measurer.Run(
|
err := measurer.Run(
|
||||||
|
@ -929,3 +898,45 @@ func TestSummaryKeysWorksAsIntended(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTargetResultsFillSummaryDirPort(t *testing.T) {
|
||||||
|
tr := &TargetResults{
|
||||||
|
TargetProtocol: "dir_port",
|
||||||
|
TCPConnect: oonidatamodel.TCPConnectList{{
|
||||||
|
IP: "1.2.3.4",
|
||||||
|
Port: 443,
|
||||||
|
Status: oonidatamodel.TCPConnectStatus{
|
||||||
|
Failure: nil,
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
tr.fillSummary()
|
||||||
|
if tr.DirPortCount != 1 {
|
||||||
|
t.Fatal("unexpected dirPortCount")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTestKeysFillToplevelKeysCoverMissingFields(t *testing.T) {
|
||||||
|
failureString := "eof_error"
|
||||||
|
tk := &TestKeys{
|
||||||
|
Targets: map[string]TargetResults{
|
||||||
|
"foobar": {Failure: &failureString, TargetProtocol: "dir_port"},
|
||||||
|
"baz": {TargetProtocol: "dir_port"},
|
||||||
|
"jafar": {Failure: &failureString, TargetProtocol: "or_port_dirauth"},
|
||||||
|
"jasmine": {TargetProtocol: "or_port_dirauth"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tk.fillToplevelKeys()
|
||||||
|
if tk.DirPortTotal != 2 {
|
||||||
|
t.Fatal("unexpected DirPortTotal")
|
||||||
|
}
|
||||||
|
if tk.DirPortAccessible != 1 {
|
||||||
|
t.Fatal("unexpected DirPortAccessible")
|
||||||
|
}
|
||||||
|
if tk.ORPortDirauthTotal != 2 {
|
||||||
|
t.Fatal("unexpected ORPortDirauthTotal")
|
||||||
|
}
|
||||||
|
if tk.ORPortDirauthAccessible != 1 {
|
||||||
|
t.Fatal("unexpected ORPortDirauthAccessible")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,30 +12,32 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/kvstore"
|
"github.com/ooni/probe-cli/v3/internal/engine/kvstore"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/probeservices"
|
"github.com/ooni/probe-cli/v3/internal/engine/probeservices"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/probeservices/testorchestra"
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/runtimex"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Session allows to mock sessions.
|
// Session allows to mock sessions.
|
||||||
type Session struct {
|
type Session struct {
|
||||||
MockableTestHelpers map[string][]model.Service
|
MockableTestHelpers map[string][]model.Service
|
||||||
MockableHTTPClient *http.Client
|
MockableHTTPClient *http.Client
|
||||||
MockableLogger model.Logger
|
MockableLogger model.Logger
|
||||||
MockableMaybeResolverIP string
|
MockableMaybeResolverIP string
|
||||||
MockableOrchestraClient model.ExperimentOrchestraClient
|
MockableProbeASNString string
|
||||||
MockableOrchestraClientError error
|
MockableProbeCC string
|
||||||
MockableProbeASNString string
|
MockableProbeIP string
|
||||||
MockableProbeCC string
|
MockableProbeNetworkName string
|
||||||
MockableProbeIP string
|
MockableProxyURL *url.URL
|
||||||
MockableProbeNetworkName string
|
MockableFetchPsiphonConfigResult []byte
|
||||||
MockableProxyURL *url.URL
|
MockableFetchPsiphonConfigErr error
|
||||||
MockableResolverIP string
|
MockableFetchTorTargetsResult map[string]model.TorTarget
|
||||||
MockableSoftwareName string
|
MockableFetchTorTargetsErr error
|
||||||
MockableSoftwareVersion string
|
MockableFetchURLListResult []model.URLInfo
|
||||||
MockableTempDir string
|
MockableFetchURLListErr error
|
||||||
MockableTorArgs []string
|
MockableResolverIP string
|
||||||
MockableTorBinary string
|
MockableSoftwareName string
|
||||||
MockableUserAgent string
|
MockableSoftwareVersion string
|
||||||
|
MockableTempDir string
|
||||||
|
MockableTorArgs []string
|
||||||
|
MockableTorBinary string
|
||||||
|
MockableUserAgent string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTestHelpersByName implements ExperimentSession.GetTestHelpersByName
|
// GetTestHelpersByName implements ExperimentSession.GetTestHelpersByName
|
||||||
|
@ -49,6 +51,23 @@ func (sess *Session) DefaultHTTPClient() *http.Client {
|
||||||
return sess.MockableHTTPClient
|
return sess.MockableHTTPClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchPsiphonConfig implements ExperimentSession.FetchPsiphonConfig
|
||||||
|
func (sess *Session) FetchPsiphonConfig(ctx context.Context) ([]byte, error) {
|
||||||
|
return sess.MockableFetchPsiphonConfigResult, sess.MockableFetchPsiphonConfigErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchTorTargets implements ExperimentSession.TorTargets
|
||||||
|
func (sess *Session) FetchTorTargets(
|
||||||
|
ctx context.Context, cc string) (map[string]model.TorTarget, error) {
|
||||||
|
return sess.MockableFetchTorTargetsResult, sess.MockableFetchTorTargetsErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchURLList implements ExperimentSession.FetchURLList.
|
||||||
|
func (sess *Session) FetchURLList(
|
||||||
|
ctx context.Context, config model.URLListConfig) ([]model.URLInfo, error) {
|
||||||
|
return sess.MockableFetchURLListResult, sess.MockableFetchURLListErr
|
||||||
|
}
|
||||||
|
|
||||||
// KeyValueStore returns the configured key-value store.
|
// KeyValueStore returns the configured key-value store.
|
||||||
func (sess *Session) KeyValueStore() model.KeyValueStore {
|
func (sess *Session) KeyValueStore() model.KeyValueStore {
|
||||||
return kvstore.NewMemoryKeyValueStore()
|
return kvstore.NewMemoryKeyValueStore()
|
||||||
|
@ -64,29 +83,6 @@ func (sess *Session) MaybeResolverIP() string {
|
||||||
return sess.MockableMaybeResolverIP
|
return sess.MockableMaybeResolverIP
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOrchestraClient implements ExperimentSession.NewOrchestraClient
|
|
||||||
func (sess *Session) NewOrchestraClient(ctx context.Context) (model.ExperimentOrchestraClient, error) {
|
|
||||||
if sess.MockableOrchestraClient != nil {
|
|
||||||
return sess.MockableOrchestraClient, nil
|
|
||||||
}
|
|
||||||
if sess.MockableOrchestraClientError != nil {
|
|
||||||
return nil, sess.MockableOrchestraClientError
|
|
||||||
}
|
|
||||||
clnt, err := probeservices.NewClient(sess, model.Service{
|
|
||||||
Address: "https://ams-pg-test.ooni.org/",
|
|
||||||
Type: "https",
|
|
||||||
})
|
|
||||||
runtimex.PanicOnError(err, "orchestra.NewClient should not fail here")
|
|
||||||
meta := testorchestra.MetadataFixture()
|
|
||||||
if err := clnt.MaybeRegister(ctx, meta); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := clnt.MaybeLogin(ctx); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return clnt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProbeASNString implements ExperimentSession.ProbeASNString
|
// ProbeASNString implements ExperimentSession.ProbeASNString
|
||||||
func (sess *Session) ProbeASNString() string {
|
func (sess *Session) ProbeASNString() string {
|
||||||
return sess.MockableProbeASNString
|
return sess.MockableProbeASNString
|
||||||
|
@ -152,42 +148,3 @@ var _ probeservices.Session = &Session{}
|
||||||
var _ psiphonx.Session = &Session{}
|
var _ psiphonx.Session = &Session{}
|
||||||
var _ tunnel.Session = &Session{}
|
var _ tunnel.Session = &Session{}
|
||||||
var _ torx.Session = &Session{}
|
var _ torx.Session = &Session{}
|
||||||
|
|
||||||
// ExperimentOrchestraClient is the experiment's view of
|
|
||||||
// a client for querying the OONI orchestra.
|
|
||||||
type ExperimentOrchestraClient struct {
|
|
||||||
MockableCheckInInfo *model.CheckInInfo
|
|
||||||
MockableCheckInErr error
|
|
||||||
MockableFetchPsiphonConfigResult []byte
|
|
||||||
MockableFetchPsiphonConfigErr error
|
|
||||||
MockableFetchTorTargetsResult map[string]model.TorTarget
|
|
||||||
MockableFetchTorTargetsErr error
|
|
||||||
MockableFetchURLListResult []model.URLInfo
|
|
||||||
MockableFetchURLListErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckIn implements ExperimentOrchestraClient.CheckIn.
|
|
||||||
func (c ExperimentOrchestraClient) CheckIn(
|
|
||||||
ctx context.Context, config model.CheckInConfig) (*model.CheckInInfo, error) {
|
|
||||||
return c.MockableCheckInInfo, c.MockableCheckInErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchPsiphonConfig implements ExperimentOrchestraClient.FetchPsiphonConfig
|
|
||||||
func (c ExperimentOrchestraClient) FetchPsiphonConfig(
|
|
||||||
ctx context.Context) ([]byte, error) {
|
|
||||||
return c.MockableFetchPsiphonConfigResult, c.MockableFetchPsiphonConfigErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchTorTargets implements ExperimentOrchestraClient.TorTargets
|
|
||||||
func (c ExperimentOrchestraClient) FetchTorTargets(
|
|
||||||
ctx context.Context, cc string) (map[string]model.TorTarget, error) {
|
|
||||||
return c.MockableFetchTorTargetsResult, c.MockableFetchTorTargetsErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchURLList implements ExperimentOrchestraClient.FetchURLList.
|
|
||||||
func (c ExperimentOrchestraClient) FetchURLList(
|
|
||||||
ctx context.Context, config model.URLListConfig) ([]model.URLInfo, error) {
|
|
||||||
return c.MockableFetchURLListResult, c.MockableFetchURLListErr
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ model.ExperimentOrchestraClient = ExperimentOrchestraClient{}
|
|
||||||
|
|
|
@ -10,13 +10,12 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/model"
|
|
||||||
"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/ClientLibrary/clientlib"
|
"github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/ClientLibrary/clientlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Session is the way in which this package sees a Session.
|
// Session is the way in which this package sees a Session.
|
||||||
type Session interface {
|
type Session interface {
|
||||||
NewOrchestraClient(ctx context.Context) (model.ExperimentOrchestraClient, error)
|
FetchPsiphonConfig(ctx context.Context) ([]byte, error)
|
||||||
TempDir() string
|
TempDir() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,11 +86,7 @@ func Start(
|
||||||
if config.WorkDir == "" {
|
if config.WorkDir == "" {
|
||||||
config.WorkDir = sess.TempDir()
|
config.WorkDir = sess.TempDir()
|
||||||
}
|
}
|
||||||
clnt, err := sess.NewOrchestraClient(ctx)
|
configJSON, err := sess.FetchPsiphonConfig(ctx)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
configJSON, err := clnt.FetchPsiphonConfig(ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,27 +58,10 @@ func TestStartStop(t *testing.T) {
|
||||||
tunnel.Stop()
|
tunnel.Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewOrchestraClientFailure(t *testing.T) {
|
|
||||||
expected := errors.New("mocked error")
|
|
||||||
sess := &mockable.Session{
|
|
||||||
MockableOrchestraClientError: expected,
|
|
||||||
}
|
|
||||||
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{})
|
|
||||||
if !errors.Is(err, expected) {
|
|
||||||
t.Fatal("not the error we expected")
|
|
||||||
}
|
|
||||||
if tunnel != nil {
|
|
||||||
t.Fatal("expected nil tunnel here")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFetchPsiphonConfigFailure(t *testing.T) {
|
func TestFetchPsiphonConfigFailure(t *testing.T) {
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
clnt := mockable.ExperimentOrchestraClient{
|
|
||||||
MockableFetchPsiphonConfigErr: expected,
|
|
||||||
}
|
|
||||||
sess := &mockable.Session{
|
sess := &mockable.Session{
|
||||||
MockableOrchestraClient: clnt,
|
MockableFetchPsiphonConfigErr: expected,
|
||||||
}
|
}
|
||||||
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{})
|
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{})
|
||||||
if !errors.Is(err, expected) {
|
if !errors.Is(err, expected) {
|
||||||
|
@ -94,11 +77,8 @@ func TestMakeMkdirAllFailure(t *testing.T) {
|
||||||
dependencies := FakeDependencies{
|
dependencies := FakeDependencies{
|
||||||
MkdirAllErr: expected,
|
MkdirAllErr: expected,
|
||||||
}
|
}
|
||||||
clnt := mockable.ExperimentOrchestraClient{
|
|
||||||
MockableFetchPsiphonConfigResult: []byte(`{}`),
|
|
||||||
}
|
|
||||||
sess := &mockable.Session{
|
sess := &mockable.Session{
|
||||||
MockableOrchestraClient: clnt,
|
MockableFetchPsiphonConfigResult: []byte(`{}`),
|
||||||
}
|
}
|
||||||
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
|
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
|
||||||
Dependencies: dependencies,
|
Dependencies: dependencies,
|
||||||
|
@ -116,11 +96,8 @@ func TestMakeRemoveAllFailure(t *testing.T) {
|
||||||
dependencies := FakeDependencies{
|
dependencies := FakeDependencies{
|
||||||
RemoveAllErr: expected,
|
RemoveAllErr: expected,
|
||||||
}
|
}
|
||||||
clnt := mockable.ExperimentOrchestraClient{
|
|
||||||
MockableFetchPsiphonConfigResult: []byte(`{}`),
|
|
||||||
}
|
|
||||||
sess := &mockable.Session{
|
sess := &mockable.Session{
|
||||||
MockableOrchestraClient: clnt,
|
MockableFetchPsiphonConfigResult: []byte(`{}`),
|
||||||
}
|
}
|
||||||
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
|
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
|
||||||
Dependencies: dependencies,
|
Dependencies: dependencies,
|
||||||
|
@ -138,11 +115,8 @@ func TestMakeStartFailure(t *testing.T) {
|
||||||
dependencies := FakeDependencies{
|
dependencies := FakeDependencies{
|
||||||
StartErr: expected,
|
StartErr: expected,
|
||||||
}
|
}
|
||||||
clnt := mockable.ExperimentOrchestraClient{
|
|
||||||
MockableFetchPsiphonConfigResult: []byte(`{}`),
|
|
||||||
}
|
|
||||||
sess := &mockable.Session{
|
sess := &mockable.Session{
|
||||||
MockableOrchestraClient: clnt,
|
MockableFetchPsiphonConfigResult: []byte(`{}`),
|
||||||
}
|
}
|
||||||
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
|
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
|
||||||
Dependencies: dependencies,
|
Dependencies: dependencies,
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestTimeLimitedLookupFailure(t *testing.T) {
|
||||||
|
|
||||||
func TestTimeLimitedLookupWillTimeout(t *testing.T) {
|
func TestTimeLimitedLookupWillTimeout(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skipping test in short mode")
|
t.Skip("skip test in short mode")
|
||||||
}
|
}
|
||||||
reso := &Resolver{}
|
reso := &Resolver{}
|
||||||
re := &FakeResolver{
|
re := &FakeResolver{
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
func TestSessionResolverGood(t *testing.T) {
|
func TestSessionResolverGood(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skipping test in short mode")
|
t.Skip("skip test in short mode")
|
||||||
}
|
}
|
||||||
reso := &sessionresolver.Resolver{}
|
reso := &sessionresolver.Resolver{}
|
||||||
defer reso.CloseIdleConnections()
|
defer reso.CloseIdleConnections()
|
||||||
|
|
|
@ -5,29 +5,14 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExperimentOrchestraClient is the experiment's view of
|
|
||||||
// a client for querying the OONI orchestra API.
|
|
||||||
type ExperimentOrchestraClient interface {
|
|
||||||
// CheckIn calls the check-in API.
|
|
||||||
CheckIn(ctx context.Context, config CheckInConfig) (*CheckInInfo, error)
|
|
||||||
|
|
||||||
// FetchPsiphonConfig returns psiphon config from the API.
|
|
||||||
FetchPsiphonConfig(ctx context.Context) ([]byte, error)
|
|
||||||
|
|
||||||
// FetchTorTargets returns tor targets from the API.
|
|
||||||
FetchTorTargets(ctx context.Context, cc string) (map[string]TorTarget, error)
|
|
||||||
|
|
||||||
// FetchURLList returns URLs from the API.
|
|
||||||
// This method is deprecated and will be removed soon.
|
|
||||||
FetchURLList(ctx context.Context, config URLListConfig) ([]URLInfo, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExperimentSession is the experiment's view of a session.
|
// ExperimentSession is the experiment's view of a session.
|
||||||
type ExperimentSession interface {
|
type ExperimentSession interface {
|
||||||
GetTestHelpersByName(name string) ([]Service, bool)
|
GetTestHelpersByName(name string) ([]Service, bool)
|
||||||
DefaultHTTPClient() *http.Client
|
DefaultHTTPClient() *http.Client
|
||||||
|
FetchPsiphonConfig(ctx context.Context) ([]byte, error)
|
||||||
|
FetchTorTargets(ctx context.Context, cc string) (map[string]TorTarget, error)
|
||||||
|
FetchURLList(ctx context.Context, config URLListConfig) ([]URLInfo, error)
|
||||||
Logger() Logger
|
Logger() Logger
|
||||||
NewOrchestraClient(ctx context.Context) (ExperimentOrchestraClient, error)
|
|
||||||
ProbeCC() string
|
ProbeCC() string
|
||||||
ResolverIP() string
|
ResolverIP() string
|
||||||
TempDir() string
|
TempDir() string
|
||||||
|
|
|
@ -129,7 +129,7 @@ func TestNewRequestList(t *testing.T) {
|
||||||
}, {
|
}, {
|
||||||
Name: "http_response_metadata",
|
Name: "http_response_metadata",
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"Server": []string{"orchestra/0.1.0-dev"},
|
"Server": []string{"miniooni/0.1.0-dev"},
|
||||||
},
|
},
|
||||||
HTTPStatusCode: 200,
|
HTTPStatusCode: 200,
|
||||||
}, {
|
}, {
|
||||||
|
@ -194,11 +194,11 @@ func TestNewRequestList(t *testing.T) {
|
||||||
HeadersList: []archival.HTTPHeader{{
|
HeadersList: []archival.HTTPHeader{{
|
||||||
Key: "Server",
|
Key: "Server",
|
||||||
Value: archival.MaybeBinaryValue{
|
Value: archival.MaybeBinaryValue{
|
||||||
Value: "orchestra/0.1.0-dev",
|
Value: "miniooni/0.1.0-dev",
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
Headers: map[string]archival.MaybeBinaryValue{
|
Headers: map[string]archival.MaybeBinaryValue{
|
||||||
"Server": {Value: "orchestra/0.1.0-dev"},
|
"Server": {Value: "miniooni/0.1.0-dev"},
|
||||||
},
|
},
|
||||||
Locations: nil,
|
Locations: nil,
|
||||||
},
|
},
|
||||||
|
@ -223,7 +223,7 @@ func TestNewRequestList(t *testing.T) {
|
||||||
}, {
|
}, {
|
||||||
Name: "http_response_metadata",
|
Name: "http_response_metadata",
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"Server": []string{"orchestra/0.1.0-dev"},
|
"Server": []string{"miniooni/0.1.0-dev"},
|
||||||
"Location": []string{"https://x.example.com", "https://y.example.com"},
|
"Location": []string{"https://x.example.com", "https://y.example.com"},
|
||||||
},
|
},
|
||||||
HTTPStatusCode: 302,
|
HTTPStatusCode: 302,
|
||||||
|
@ -260,11 +260,11 @@ func TestNewRequestList(t *testing.T) {
|
||||||
}, {
|
}, {
|
||||||
Key: "Server",
|
Key: "Server",
|
||||||
Value: archival.MaybeBinaryValue{
|
Value: archival.MaybeBinaryValue{
|
||||||
Value: "orchestra/0.1.0-dev",
|
Value: "miniooni/0.1.0-dev",
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
Headers: map[string]archival.MaybeBinaryValue{
|
Headers: map[string]archival.MaybeBinaryValue{
|
||||||
"Server": {Value: "orchestra/0.1.0-dev"},
|
"Server": {Value: "miniooni/0.1.0-dev"},
|
||||||
"Location": {Value: "https://x.example.com"},
|
"Location": {Value: "https://x.example.com"},
|
||||||
},
|
},
|
||||||
Locations: []string{
|
Locations: []string{
|
||||||
|
|
|
@ -275,6 +275,35 @@ func (s *Session) DefaultHTTPClient() *http.Client {
|
||||||
return &http.Client{Transport: s.httpDefaultTransport}
|
return &http.Client{Transport: s.httpDefaultTransport}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FetchPsiphonConfig fetches psiphon config from the API.
|
||||||
|
func (s *Session) FetchPsiphonConfig(ctx context.Context) ([]byte, error) {
|
||||||
|
clnt, err := s.NewOrchestraClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return clnt.FetchPsiphonConfig(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchTorTargets fetches tor targets from the API.
|
||||||
|
func (s *Session) FetchTorTargets(
|
||||||
|
ctx context.Context, cc string) (map[string]model.TorTarget, error) {
|
||||||
|
clnt, err := s.NewOrchestraClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return clnt.FetchTorTargets(ctx, cc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FetchURLList fetches the URL list from the API.
|
||||||
|
func (s *Session) FetchURLList(
|
||||||
|
ctx context.Context, config model.URLListConfig) ([]model.URLInfo, error) {
|
||||||
|
clnt, err := s.NewOrchestraClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return clnt.FetchURLList(ctx, config)
|
||||||
|
}
|
||||||
|
|
||||||
// KeyValueStore returns the configured key-value store.
|
// KeyValueStore returns the configured key-value store.
|
||||||
func (s *Session) KeyValueStore() model.KeyValueStore {
|
func (s *Session) KeyValueStore() model.KeyValueStore {
|
||||||
return s.kvStore
|
return s.kvStore
|
||||||
|
@ -387,7 +416,10 @@ func (s *Session) NewSubmitter(ctx context.Context) (Submitter, error) {
|
||||||
|
|
||||||
// NewOrchestraClient creates a new orchestra client. This client is registered
|
// NewOrchestraClient creates a new orchestra client. This client is registered
|
||||||
// and logged in with the OONI orchestra. An error is returned on failure.
|
// and logged in with the OONI orchestra. An error is returned on failure.
|
||||||
func (s *Session) NewOrchestraClient(ctx context.Context) (model.ExperimentOrchestraClient, error) {
|
//
|
||||||
|
// This function is DEPRECATED. New code SHOULD NOT use it. It will eventually
|
||||||
|
// be made private or entirely removed from the codebase.
|
||||||
|
func (s *Session) NewOrchestraClient(ctx context.Context) (*probeservices.Client, error) {
|
||||||
clnt, err := s.NewProbeServicesClient(ctx)
|
clnt, err := s.NewProbeServicesClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -166,21 +166,6 @@ func newSessionForTesting(t *testing.T) *Session {
|
||||||
return sess
|
return sess
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewOrchestraClient(t *testing.T) {
|
|
||||||
if testing.Short() {
|
|
||||||
t.Skip("skip test in short mode")
|
|
||||||
}
|
|
||||||
sess := newSessionForTestingNoLookups(t)
|
|
||||||
defer sess.Close()
|
|
||||||
clnt, err := sess.NewOrchestraClient(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if clnt == nil {
|
|
||||||
t.Fatal("expected non nil client here")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInitOrchestraClientMaybeRegisterError(t *testing.T) {
|
func TestInitOrchestraClientMaybeRegisterError(t *testing.T) {
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
t.Skip("skip test in short mode")
|
t.Skip("skip test in short mode")
|
||||||
|
@ -634,3 +619,17 @@ func TestSessionNewSubmitterReturnsNonNilSubmitter(t *testing.T) {
|
||||||
t.Fatal("expected non nil submitter here")
|
t.Fatal("expected non nil submitter here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSessionFetchURLList(t *testing.T) {
|
||||||
|
if testing.Short() {
|
||||||
|
t.Skip("skip test in short mode")
|
||||||
|
}
|
||||||
|
sess := newSessionForTesting(t)
|
||||||
|
resp, err := sess.FetchURLList(context.Background(), model.URLListConfig{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatal("expected non-nil response here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -208,3 +208,42 @@ func TestSessionMaybeLookupLocationContextLookupLocationContextFailure(t *testin
|
||||||
t.Fatal("not the error we expected", err)
|
t.Fatal("not the error we expected", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSessionFetchURLListWithCancelledContext(t *testing.T) {
|
||||||
|
sess := &Session{}
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel() // cause failure
|
||||||
|
resp, err := sess.FetchURLList(ctx, model.URLListConfig{})
|
||||||
|
if !errors.Is(err, context.Canceled) {
|
||||||
|
t.Fatal("not the error we expected", err)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
t.Fatal("expected nil response here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSessionFetchTorTargetsWithCancelledContext(t *testing.T) {
|
||||||
|
sess := &Session{}
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel() // cause failure
|
||||||
|
resp, err := sess.FetchTorTargets(ctx, "IT")
|
||||||
|
if !errors.Is(err, context.Canceled) {
|
||||||
|
t.Fatal("not the error we expected", err)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
t.Fatal("expected nil response here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSessionFetchPsiphonConfigWithCancelledContext(t *testing.T) {
|
||||||
|
sess := &Session{}
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel() // cause failure
|
||||||
|
resp, err := sess.FetchPsiphonConfig(ctx)
|
||||||
|
if !errors.Is(err, context.Canceled) {
|
||||||
|
t.Fatal("not the error we expected", err)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
t.Fatal("expected nil response here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user