Skip to content

Commit

Permalink
psiphon: fetch and use config from OONI orchestra
Browse files Browse the repository at this point in the history
Closes #167
  • Loading branch information
bassosimone committed Dec 17, 2019
1 parent c4d0086 commit 89e9a14
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 53 deletions.
11 changes: 6 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
asn.mmdb
ca-bundle.pem
country.mmdb
miniooni
report.jsonl
/asn.mmdb
/ca-bundle.pem
/country.mmdb
/miniooni
/oonipsiphon/
/report.jsonl
4 changes: 0 additions & 4 deletions experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"errors"
"path/filepath"
"reflect"
"time"

Expand Down Expand Up @@ -348,9 +347,6 @@ var experimentsByName = map[string]func(*Session) *ExperimentBuilder{
return psiphon.NewExperiment(session.session, *config.(*psiphon.Config))
},
config: &psiphon.Config{
ConfigFilePath: filepath.Join(
session.session.AssetsDir, "psiphon_config.json",
),
WorkDir: session.session.TempDir,
},
needsInput: false,
Expand Down
2 changes: 1 addition & 1 deletion experiment/example/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func measure(
testkeys := &TestKeys{Success: err == nil}
measurement.TestKeys = testkeys
time.Sleep(time.Duration(config.SleepTime))
callbacks.OnProgress(100, config.Message)
callbacks.OnProgress(1.0, config.Message)
callbacks.OnDataUsage(0, 0)
return err
}
Expand Down
3 changes: 0 additions & 3 deletions experiment/psiphon/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ const (

// Config contains the experiment's configuration.
type Config struct {
// ConfigFilePath is the path where Psiphon config file is located.
ConfigFilePath string `ooni:"configuration file path"`

// WorkDir is the directory where Psiphon should store
// its configuration database.
WorkDir string `ooni:"experiment working directory"`
Expand Down
22 changes: 11 additions & 11 deletions experiment/psiphon/psiphon.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,6 @@ func newRunner(config Config, callbacks handler.Callbacks) *runner {
}
}

func (r *runner) readconfig() ([]byte, error) {
configJSON, err := r.ioutilReadFile(r.config.ConfigFilePath)
if err != nil {
return nil, err
}
return configJSON, nil
}

func (r *runner) makeworkingdir() (string, error) {
if r.config.WorkDir == "" {
return "", errors.New("WorkDir is empty")
Expand Down Expand Up @@ -143,8 +135,12 @@ func (r *runner) usetunnel(
return nil
}

func (r *runner) run(ctx context.Context, logger log.Logger) error {
configJSON, err := r.readconfig()
func (r *runner) run(
ctx context.Context,
logger log.Logger,
fetchPsiphonConfig func(ctx context.Context) ([]byte, error),
) error {
configJSON, err := fetchPsiphonConfig(ctx)
if err != nil {
s := err.Error()
r.testkeys.Failure = &s
Expand Down Expand Up @@ -199,6 +195,10 @@ func (m *measurer) measure(
ctx context.Context, sess *session.Session,
measurement *model.Measurement, callbacks handler.Callbacks,
) error {
clnt, err := sess.NewOrchestraClient(ctx)
if err != nil {
return err
}
const maxruntime = 60
ctx, cancel := context.WithTimeout(ctx, maxruntime*time.Second)
var wg sync.WaitGroup
Expand All @@ -207,7 +207,7 @@ func (m *measurer) measure(
r := newRunner(m.config, callbacks)
measurement.TestKeys = r.testkeys
r.testkeys.MaxRuntime = maxruntime
err := r.run(ctx, sess.Logger)
err = r.run(ctx, sess.Logger, clnt.FetchPsiphonConfig)
cancel()
wg.Wait()
return err
Expand Down
85 changes: 61 additions & 24 deletions experiment/psiphon/psiphon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ package psiphon
import (
"context"
"errors"
"net/http"
"os"
"strings"
"testing"

"github.com/apex/log"
"github.com/ooni/probe-engine/experiment/handler"
"github.com/ooni/probe-engine/internal/orchestra"
"github.com/ooni/probe-engine/internal/orchestra/statefile"
"github.com/ooni/probe-engine/internal/orchestra/testorchestra"
"github.com/ooni/probe-engine/model"
"github.com/ooni/probe-engine/session"
)
Expand All @@ -36,30 +40,18 @@ func TestUnitMeasureWithCancelledContext(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel() // fail immediately
err := m.measure(
ctx, &session.Session{Logger: log.Log},
ctx, newsession(),
new(model.Measurement),
handler.NewPrinterCallbacks(log.Log),
)
if err == nil {
t.Fatal("expected an error here")
}
if !strings.HasSuffix(err.Error(), "controller.Run exited unexpectedly") {
if !strings.HasSuffix(err.Error(), "All IP lookuppers failed") {
t.Fatal("not the error we expected")
}
}

func TestUnitReadConfig(t *testing.T) {
r := newRunner(makeconfig(), handler.NewPrinterCallbacks(log.Log))
r.config.ConfigFilePath = "../../testdata/nonexistent_config.json"
configJSON, err := r.readconfig()
if err == nil {
t.Fatal("expected an error here")
}
if configJSON != nil {
t.Fatal("expected nil configJSON")
}
}

func TestUnitMakeWorkingDirEmptyWorkingDir(t *testing.T) {
r := newRunner(makeconfig(), handler.NewPrinterCallbacks(log.Log))
r.config.WorkDir = ""
Expand Down Expand Up @@ -102,12 +94,14 @@ func TestUnitMakeWorkingDirOsMkdirAllError(t *testing.T) {
}
}

func TestUnitRunReadconfigError(t *testing.T) {
func TestUnitRunFetchPsiphonConfigError(t *testing.T) {
r := newRunner(makeconfig(), handler.NewPrinterCallbacks(log.Log))
r.config.ConfigFilePath = "../../testdata/nonexistent_config.json"
err := r.run(context.Background(), log.Log)
if err == nil {
t.Fatal("expected an error here")
expected := errors.New("mocked error")
err := r.run(context.Background(), log.Log, func(context.Context) ([]byte, error) {
return nil, expected
})
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
}
}

Expand All @@ -117,18 +111,51 @@ func TestUnitRunMakeworkingdirError(t *testing.T) {
r.osRemoveAll = func(path string) error {
return expected
}
err := r.run(context.Background(), log.Log)
clnt, err := newclient()
if err != nil {
t.Fatal(err)
}
err = r.run(context.Background(), log.Log, clnt.FetchPsiphonConfig)
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
}
}

func TestUnitRunStartTunnelError(t *testing.T) {
r := newRunner(makeconfig(), handler.NewPrinterCallbacks(log.Log))
err := r.run(context.Background(), log.Log, func(context.Context) ([]byte, error) {
return []byte("{"), nil
})
if !strings.HasSuffix(err.Error(), "unexpected end of JSON input") {
t.Fatal("not the error we expected")
}
}

func newclient() (*orchestra.Client, error) {
clnt := orchestra.NewClient(
http.DefaultClient,
log.Log,
"miniooni/0.1.0-dev",
statefile.NewMemory("/tmp"),
)
clnt.OrchestraBaseURL = "https://ps-test.ooni.io"
clnt.RegistryBaseURL = "https://ps-test.ooni.io"
ctx := context.Background()
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
}

func TestIntegration(t *testing.T) {
m := &measurer{config: makeconfig()}
sess := &session.Session{Logger: log.Log}
if err := m.measure(
context.Background(),
sess,
newsession(),
new(model.Measurement),
handler.NewPrinterCallbacks(log.Log),
); err != nil {
Expand All @@ -148,7 +175,17 @@ func TestUnitUsetunnel(t *testing.T) {

func makeconfig() Config {
return Config{
ConfigFilePath: "../../testdata/psiphon_config.json",
WorkDir: "../../testdata/psiphon_unit_tests",
WorkDir: "../../testdata/psiphon_unit_tests",
}
}

func newsession() *session.Session {
return session.New(
log.Log,
"miniooni",
"0.1.0-dev",
"../../testdata",
nil, nil,
"../../testdata",
)
}
54 changes: 54 additions & 0 deletions session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import (
"github.com/ooni/probe-engine/geoiplookup/mmdblookup"
"github.com/ooni/probe-engine/geoiplookup/resolverlookup"
"github.com/ooni/probe-engine/httpx/httpx"
"github.com/ooni/probe-engine/internal/orchestra"
"github.com/ooni/probe-engine/internal/orchestra/metadata"
"github.com/ooni/probe-engine/internal/orchestra/statefile"
"github.com/ooni/probe-engine/internal/platform"
"github.com/ooni/probe-engine/log"
"github.com/ooni/probe-engine/model"
"github.com/ooni/probe-engine/resources"
Expand Down Expand Up @@ -191,6 +195,56 @@ func (s *Session) ResolverIP() string {
return ip
}

func (s *Session) initOrchestraClient(
ctx context.Context,
clnt *orchestra.Client,
maybeLogin func(ctx context.Context) error,
) (*orchestra.Client, error) {
meta := metadata.Metadata{
Platform: platform.Name(),
ProbeASN: s.ProbeASNString(),
ProbeCC: s.ProbeCC(),
SoftwareName: s.SoftwareName,
SoftwareVersion: s.SoftwareVersion,
SupportedTests: []string{
// TODO(bassosimone): do we need to declare more tests
// here? I believe we're not using this functionality of
// orchestra for now. Plus, we can always change later.
"web_connectivity",
},
}
if err := clnt.MaybeRegister(ctx, meta); err != nil {
return nil, err
}
if err := maybeLogin(ctx); err != nil {
return nil, err
}
return clnt, nil
}

// NewOrchestraClient creates a new orchestra client. This client is registered
// and logged in with the OONI orchestra. An error is returned on failure.
func (s *Session) NewOrchestraClient(ctx context.Context) (*orchestra.Client, error) {
clnt := orchestra.NewClient(
s.HTTPDefaultClient,
s.Logger,
s.UserAgent(),
statefile.NewMemory(s.AssetsDir),
)
// Make sure we have location info so we can fill metadata
if err := s.MaybeLookupLocation(ctx); err != nil {
return nil, err
}
// TODO(bassosimone): until we implement persistent storage
// it is advisable to use the testing service. The related
// tracking GitHub issue is ooni/probe-engine#164.
clnt.OrchestraBaseURL = "https://ps-test.ooni.io"
clnt.RegistryBaseURL = "https://ps-test.ooni.io"
return s.initOrchestraClient(
ctx, clnt, clnt.MaybeLogin,
)
}

func (s *Session) fetchResourcesIdempotent(ctx context.Context) error {
return (&resources.Client{
HTTPClient: s.HTTPDefaultClient, // proxy is OK
Expand Down

0 comments on commit 89e9a14

Please sign in to comment.