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:
Simone Basso 2021-04-02 12:03:18 +02:00 committed by GitHub
commit 79e8424677
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 200 additions and 210 deletions

View file

@ -12,30 +12,32 @@ import (
"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/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.
type Session struct {
MockableTestHelpers map[string][]model.Service
MockableHTTPClient *http.Client
MockableLogger model.Logger
MockableMaybeResolverIP string
MockableOrchestraClient model.ExperimentOrchestraClient
MockableOrchestraClientError error
MockableProbeASNString string
MockableProbeCC string
MockableProbeIP string
MockableProbeNetworkName string
MockableProxyURL *url.URL
MockableResolverIP string
MockableSoftwareName string
MockableSoftwareVersion string
MockableTempDir string
MockableTorArgs []string
MockableTorBinary string
MockableUserAgent string
MockableTestHelpers map[string][]model.Service
MockableHTTPClient *http.Client
MockableLogger model.Logger
MockableMaybeResolverIP string
MockableProbeASNString string
MockableProbeCC string
MockableProbeIP string
MockableProbeNetworkName string
MockableProxyURL *url.URL
MockableFetchPsiphonConfigResult []byte
MockableFetchPsiphonConfigErr error
MockableFetchTorTargetsResult map[string]model.TorTarget
MockableFetchTorTargetsErr error
MockableFetchURLListResult []model.URLInfo
MockableFetchURLListErr error
MockableResolverIP string
MockableSoftwareName string
MockableSoftwareVersion string
MockableTempDir string
MockableTorArgs []string
MockableTorBinary string
MockableUserAgent string
}
// GetTestHelpersByName implements ExperimentSession.GetTestHelpersByName
@ -49,6 +51,23 @@ func (sess *Session) DefaultHTTPClient() *http.Client {
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.
func (sess *Session) KeyValueStore() model.KeyValueStore {
return kvstore.NewMemoryKeyValueStore()
@ -64,29 +83,6 @@ func (sess *Session) MaybeResolverIP() string {
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
func (sess *Session) ProbeASNString() string {
return sess.MockableProbeASNString
@ -152,42 +148,3 @@ var _ probeservices.Session = &Session{}
var _ psiphonx.Session = &Session{}
var _ tunnel.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{}

View file

@ -10,13 +10,12 @@ import (
"path/filepath"
"time"
"github.com/ooni/probe-cli/v3/internal/engine/model"
"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.
type Session interface {
NewOrchestraClient(ctx context.Context) (model.ExperimentOrchestraClient, error)
FetchPsiphonConfig(ctx context.Context) ([]byte, error)
TempDir() string
}
@ -87,11 +86,7 @@ func Start(
if config.WorkDir == "" {
config.WorkDir = sess.TempDir()
}
clnt, err := sess.NewOrchestraClient(ctx)
if err != nil {
return nil, err
}
configJSON, err := clnt.FetchPsiphonConfig(ctx)
configJSON, err := sess.FetchPsiphonConfig(ctx)
if err != nil {
return nil, err
}

View file

@ -58,27 +58,10 @@ func TestStartStop(t *testing.T) {
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) {
expected := errors.New("mocked error")
clnt := mockable.ExperimentOrchestraClient{
MockableFetchPsiphonConfigErr: expected,
}
sess := &mockable.Session{
MockableOrchestraClient: clnt,
MockableFetchPsiphonConfigErr: expected,
}
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{})
if !errors.Is(err, expected) {
@ -94,11 +77,8 @@ func TestMakeMkdirAllFailure(t *testing.T) {
dependencies := FakeDependencies{
MkdirAllErr: expected,
}
clnt := mockable.ExperimentOrchestraClient{
MockableFetchPsiphonConfigResult: []byte(`{}`),
}
sess := &mockable.Session{
MockableOrchestraClient: clnt,
MockableFetchPsiphonConfigResult: []byte(`{}`),
}
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
Dependencies: dependencies,
@ -116,11 +96,8 @@ func TestMakeRemoveAllFailure(t *testing.T) {
dependencies := FakeDependencies{
RemoveAllErr: expected,
}
clnt := mockable.ExperimentOrchestraClient{
MockableFetchPsiphonConfigResult: []byte(`{}`),
}
sess := &mockable.Session{
MockableOrchestraClient: clnt,
MockableFetchPsiphonConfigResult: []byte(`{}`),
}
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
Dependencies: dependencies,
@ -138,11 +115,8 @@ func TestMakeStartFailure(t *testing.T) {
dependencies := FakeDependencies{
StartErr: expected,
}
clnt := mockable.ExperimentOrchestraClient{
MockableFetchPsiphonConfigResult: []byte(`{}`),
}
sess := &mockable.Session{
MockableOrchestraClient: clnt,
MockableFetchPsiphonConfigResult: []byte(`{}`),
}
tunnel, err := psiphonx.Start(context.Background(), sess, psiphonx.Config{
Dependencies: dependencies,

View file

@ -62,7 +62,7 @@ func TestTimeLimitedLookupFailure(t *testing.T) {
func TestTimeLimitedLookupWillTimeout(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode")
t.Skip("skip test in short mode")
}
reso := &Resolver{}
re := &FakeResolver{

View file

@ -9,7 +9,7 @@ import (
func TestSessionResolverGood(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode")
t.Skip("skip test in short mode")
}
reso := &sessionresolver.Resolver{}
defer reso.CloseIdleConnections()