ooni-probe-cli/internal/engine/experiment/torsf/torsf_test.go
Simone Basso a50efdbcf1
feat(torsf): experiment that bootstraps tor using snowflake (#387)
The current implementation assumes the user has already installed tor
on the current system. If tor is not present, the experiment fails.

This is meant to be the first version of this experiment.

We are going to add more functionality in subsequent revisions of
this experiment, once we've collected more feedback.

Reference issue: https://github.com/ooni/probe/issues/1565.

Here's the spec PR: https://github.com/ooni/spec/pull/218.

Here's the issue tracking future work: https://github.com/ooni/probe/issues/1686
2021-06-18 13:51:18 +02:00

168 lines
4.1 KiB
Go

package torsf
import (
"context"
"errors"
"net/url"
"testing"
"time"
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/internal/engine/internal/mockable"
"github.com/ooni/probe-cli/v3/internal/engine/model"
"github.com/ooni/probe-cli/v3/internal/tunnel"
)
func TestExperimentNameAndVersion(t *testing.T) {
m := NewExperimentMeasurer(Config{})
if m.ExperimentName() != "torsf" {
t.Fatal("invalid experiment name")
}
if m.ExperimentVersion() != "0.1.0" {
t.Fatal("invalid experiment version")
}
}
// mockedTunnel is a mocked tunnel.
type mockedTunnel struct {
bootstrapTime time.Duration
proxyURL *url.URL
}
// BootstrapTime implements Tunnel.BootstrapTime.
func (mt *mockedTunnel) BootstrapTime() time.Duration {
return mt.bootstrapTime
}
// SOCKS5ProxyURL implements Tunnel.SOCKS5ProxyURL.
func (mt *mockedTunnel) SOCKS5ProxyURL() *url.URL {
return mt.proxyURL
}
// Stop implements Tunnel.Stop.
func (mt *mockedTunnel) Stop() {
// nothing
}
func TestSuccessWithMockedTunnelStart(t *testing.T) {
bootstrapTime := 400 * time.Millisecond
m := &Measurer{
config: Config{},
mockStartTunnel: func(ctx context.Context, config *tunnel.Config) (tunnel.Tunnel, error) {
// run for some time so we also exercise printing progress.
time.Sleep(bootstrapTime)
return &mockedTunnel{
bootstrapTime: time.Duration(bootstrapTime),
}, nil
},
}
ctx := context.Background()
measurement := &model.Measurement{}
sess := &mockable.Session{}
callbacks := &model.PrinterCallbacks{
Logger: log.Log,
}
if err := m.Run(ctx, sess, measurement, callbacks); err != nil {
t.Fatal(err)
}
tk := measurement.TestKeys.(*TestKeys)
if tk.BootstrapTime != bootstrapTime.Seconds() {
t.Fatal("unexpected bootstrap time")
}
}
func TestFailureToStartTunnel(t *testing.T) {
expected := errors.New("mocked error")
m := &Measurer{
config: Config{},
mockStartTunnel: func(ctx context.Context, config *tunnel.Config) (tunnel.Tunnel, error) {
return nil, expected
},
}
ctx := context.Background()
measurement := &model.Measurement{}
sess := &mockable.Session{}
callbacks := &model.PrinterCallbacks{
Logger: log.Log,
}
if err := m.Run(ctx, sess, measurement, callbacks); err != nil {
t.Fatal(err)
}
tk := measurement.TestKeys.(*TestKeys)
if tk.BootstrapTime != 0 {
t.Fatal("unexpected bootstrap time")
}
if tk.Failure == nil {
t.Fatal("unexpectedly nil failure string")
}
if *tk.Failure != "unknown_failure: mocked error" {
t.Fatal("unexpected failure string", *tk.Failure)
}
}
func TestFailureToStartPTXListener(t *testing.T) {
expected := errors.New("mocked error")
m := &Measurer{
config: Config{},
mockStartListener: func() error {
return expected
},
}
ctx := context.Background()
measurement := &model.Measurement{}
sess := &mockable.Session{}
callbacks := &model.PrinterCallbacks{
Logger: log.Log,
}
if err := m.Run(ctx, sess, measurement, callbacks); !errors.Is(err, expected) {
t.Fatal("not the error we expected", err)
}
tk := measurement.TestKeys.(*TestKeys)
if tk.BootstrapTime != 0 {
t.Fatal("unexpected bootstrap time")
}
if tk.Failure == nil {
t.Fatal("unexpectedly nil failure string")
}
if *tk.Failure != "unknown_failure: mocked error" {
t.Fatal("unexpected failure string", *tk.Failure)
}
}
func TestStartWithCancelledContext(t *testing.T) {
m := &Measurer{config: Config{}}
ctx, cancel := context.WithCancel(context.Background())
cancel() // fail immediately
measurement := &model.Measurement{}
sess := &mockable.Session{}
callbacks := &model.PrinterCallbacks{
Logger: log.Log,
}
if err := m.Run(ctx, sess, measurement, callbacks); err != nil {
t.Fatal(err)
}
tk := measurement.TestKeys.(*TestKeys)
if tk.BootstrapTime != 0 {
t.Fatal("unexpected bootstrap time")
}
if tk.Failure == nil {
t.Fatal("unexpected nil failure")
}
if *tk.Failure != "interrupted" {
t.Fatal("unexpected failure string", *tk.Failure)
}
}
func TestGetSummaryKeys(t *testing.T) {
measurement := &model.Measurement{}
m := &Measurer{}
sk, err := m.GetSummaryKeys(measurement)
if err != nil {
t.Fatal(err)
}
rsk := sk.(*SummaryKeys)
if rsk.IsAnomaly {
t.Fatal("expected no anomaly here")
}
}