This diff forward ports bc4b9f1ea89158bfa7b7a80ae59a90b43c784ed2 to `master`. See https://github.com/ooni/probe/issues/1903
This commit is contained in:
		
							parent
							
								
									ece6f3d48d
								
							
						
					
					
						commit
						ee5be24900
					
				| @ -1,22 +1,20 @@ | ||||
| package tasks | ||||
| package oonimkall | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| ) | ||||
| import "fmt" | ||||
| 
 | ||||
| // ChanLogger is a logger targeting a channel | ||||
| type ChanLogger struct { | ||||
| 	emitter    *EventEmitter | ||||
| // chanLogger is a logger targeting a channel | ||||
| type chanLogger struct { | ||||
| 	emitter    *eventEmitter | ||||
| 	hasdebug   bool | ||||
| 	hasinfo    bool | ||||
| 	haswarning bool | ||||
| 	out        chan<- *Event | ||||
| 	out        chan<- *event | ||||
| } | ||||
| 
 | ||||
| // Debug implements Logger.Debug | ||||
| func (cl *ChanLogger) Debug(msg string) { | ||||
| func (cl *chanLogger) Debug(msg string) { | ||||
| 	if cl.hasdebug { | ||||
| 		cl.emitter.Emit("log", EventLog{ | ||||
| 		cl.emitter.Emit("log", eventLog{ | ||||
| 			LogLevel: "DEBUG", | ||||
| 			Message:  msg, | ||||
| 		}) | ||||
| @ -24,16 +22,16 @@ func (cl *ChanLogger) Debug(msg string) { | ||||
| } | ||||
| 
 | ||||
| // Debugf implements Logger.Debugf | ||||
| func (cl *ChanLogger) Debugf(format string, v ...interface{}) { | ||||
| func (cl *chanLogger) Debugf(format string, v ...interface{}) { | ||||
| 	if cl.hasdebug { | ||||
| 		cl.Debug(fmt.Sprintf(format, v...)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Info implements Logger.Info | ||||
| func (cl *ChanLogger) Info(msg string) { | ||||
| func (cl *chanLogger) Info(msg string) { | ||||
| 	if cl.hasinfo { | ||||
| 		cl.emitter.Emit("log", EventLog{ | ||||
| 		cl.emitter.Emit("log", eventLog{ | ||||
| 			LogLevel: "INFO", | ||||
| 			Message:  msg, | ||||
| 		}) | ||||
| @ -41,16 +39,16 @@ func (cl *ChanLogger) Info(msg string) { | ||||
| } | ||||
| 
 | ||||
| // Infof implements Logger.Infof | ||||
| func (cl *ChanLogger) Infof(format string, v ...interface{}) { | ||||
| func (cl *chanLogger) Infof(format string, v ...interface{}) { | ||||
| 	if cl.hasinfo { | ||||
| 		cl.Info(fmt.Sprintf(format, v...)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Warn implements Logger.Warn | ||||
| func (cl *ChanLogger) Warn(msg string) { | ||||
| func (cl *chanLogger) Warn(msg string) { | ||||
| 	if cl.haswarning { | ||||
| 		cl.emitter.Emit("log", EventLog{ | ||||
| 		cl.emitter.Emit("log", eventLog{ | ||||
| 			LogLevel: "WARNING", | ||||
| 			Message:  msg, | ||||
| 		}) | ||||
| @ -58,16 +56,16 @@ func (cl *ChanLogger) Warn(msg string) { | ||||
| } | ||||
| 
 | ||||
| // Warnf implements Logger.Warnf | ||||
| func (cl *ChanLogger) Warnf(format string, v ...interface{}) { | ||||
| func (cl *chanLogger) Warnf(format string, v ...interface{}) { | ||||
| 	if cl.haswarning { | ||||
| 		cl.Warn(fmt.Sprintf(format, v...)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NewChanLogger creates a new ChanLogger instance. | ||||
| func NewChanLogger(emitter *EventEmitter, logLevel string, | ||||
| 	out chan<- *Event) *ChanLogger { | ||||
| 	cl := &ChanLogger{ | ||||
| // newChanLogger creates a new ChanLogger instance. | ||||
| func newChanLogger(emitter *eventEmitter, logLevel string, | ||||
| 	out chan<- *event) *chanLogger { | ||||
| 	cl := &chanLogger{ | ||||
| 		emitter: emitter, | ||||
| 		out:     out, | ||||
| 	} | ||||
| @ -1,14 +1,14 @@ | ||||
| package tasks | ||||
| package oonimkall | ||||
| 
 | ||||
| type eventEmpty struct{} | ||||
| 
 | ||||
| // EventFailure contains information on a failure. | ||||
| type EventFailure struct { | ||||
| // eventFailure contains information on a failure. | ||||
| type eventFailure struct { | ||||
| 	Failure string `json:"failure"` | ||||
| } | ||||
| 
 | ||||
| // EventLog is an event containing a log message. | ||||
| type EventLog struct { | ||||
| // eventLog is an event containing a log message. | ||||
| type eventLog struct { | ||||
| 	LogLevel string `json:"log_level"` | ||||
| 	Message  string `json:"message"` | ||||
| } | ||||
| @ -33,8 +33,8 @@ type eventStatusGeoIPLookup struct { | ||||
| 	ProbeNetworkName string `json:"probe_network_name"` | ||||
| } | ||||
| 
 | ||||
| // EventStatusProgress reports progress information. | ||||
| type EventStatusProgress struct { | ||||
| // eventStatusProgress reports progress information. | ||||
| type eventStatusProgress struct { | ||||
| 	Message    string  `json:"message"` | ||||
| 	Percentage float64 `json:"percentage"` | ||||
| } | ||||
| @ -49,9 +49,9 @@ type eventStatusResolverLookup struct { | ||||
| 	ResolverNetworkName string `json:"resolver_network_name"` | ||||
| } | ||||
| 
 | ||||
| // Event is an event emitted by a task. This structure extends the event | ||||
| // event is an event emitted by a task. This structure extends the event | ||||
| // described by MK v0.10.9 FFI API (https://git.io/Jv4Rv). | ||||
| type Event struct { | ||||
| type event struct { | ||||
| 	Key   string      `json:"key"` | ||||
| 	Value interface{} `json:"value"` | ||||
| } | ||||
							
								
								
									
										40
									
								
								pkg/oonimkall/eventemitter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								pkg/oonimkall/eventemitter.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| package oonimkall | ||||
| 
 | ||||
| // eventEmitter emits event on a channel | ||||
| type eventEmitter struct { | ||||
| 	disabled map[string]bool | ||||
| 	out      chan<- *event | ||||
| } | ||||
| 
 | ||||
| // newEventEmitter creates a new Emitter | ||||
| func newEventEmitter(disabledEvents []string, out chan<- *event) *eventEmitter { | ||||
| 	ee := &eventEmitter{out: out} | ||||
| 	ee.disabled = make(map[string]bool) | ||||
| 	for _, eventname := range disabledEvents { | ||||
| 		ee.disabled[eventname] = true | ||||
| 	} | ||||
| 	return ee | ||||
| } | ||||
| 
 | ||||
| // EmitFailureStartup emits the failureStartup event | ||||
| func (ee *eventEmitter) EmitFailureStartup(failure string) { | ||||
| 	ee.EmitFailureGeneric(failureStartup, failure) | ||||
| } | ||||
| 
 | ||||
| // EmitFailureGeneric emits a failure event | ||||
| func (ee *eventEmitter) EmitFailureGeneric(name, failure string) { | ||||
| 	ee.Emit(name, eventFailure{Failure: failure}) | ||||
| } | ||||
| 
 | ||||
| // EmitStatusProgress emits the status.Progress event | ||||
| func (ee *eventEmitter) EmitStatusProgress(percentage float64, message string) { | ||||
| 	ee.Emit(statusProgress, eventStatusProgress{Message: message, Percentage: percentage}) | ||||
| } | ||||
| 
 | ||||
| // Emit emits the specified event | ||||
| func (ee *eventEmitter) Emit(key string, value interface{}) { | ||||
| 	if ee.disabled[key] { | ||||
| 		return | ||||
| 	} | ||||
| 	ee.out <- &event{Key: key, Value: value} | ||||
| } | ||||
| @ -1,16 +1,12 @@ | ||||
| package tasks_test | ||||
| package oonimkall | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/ooni/probe-cli/v3/pkg/oonimkall/internal/tasks" | ||||
| ) | ||||
| import "testing" | ||||
| 
 | ||||
| func TestDisabledEvents(t *testing.T) { | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	emitter := tasks.NewEventEmitter([]string{"log"}, out) | ||||
| 	out := make(chan *event) | ||||
| 	emitter := newEventEmitter([]string{"log"}, out) | ||||
| 	go func() { | ||||
| 		emitter.Emit("log", tasks.EventLog{Message: "foo"}) | ||||
| 		emitter.Emit("log", eventLog{Message: "foo"}) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var count int64 | ||||
| @ -25,8 +21,8 @@ func TestDisabledEvents(t *testing.T) { | ||||
| } | ||||
| 
 | ||||
| func TestEmitFailureStartup(t *testing.T) { | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	emitter := tasks.NewEventEmitter([]string{}, out) | ||||
| 	out := make(chan *event) | ||||
| 	emitter := newEventEmitter([]string{}, out) | ||||
| 	go func() { | ||||
| 		emitter.EmitFailureStartup("mocked error") | ||||
| 		close(out) | ||||
| @ -34,7 +30,7 @@ func TestEmitFailureStartup(t *testing.T) { | ||||
| 	var found bool | ||||
| 	for ev := range out { | ||||
| 		if ev.Key == "failure.startup" { | ||||
| 			evv := ev.Value.(tasks.EventFailure) // panic if not castable | ||||
| 			evv := ev.Value.(eventFailure) // panic if not castable | ||||
| 			if evv.Failure == "mocked error" { | ||||
| 				found = true | ||||
| 			} | ||||
| @ -46,8 +42,8 @@ func TestEmitFailureStartup(t *testing.T) { | ||||
| } | ||||
| 
 | ||||
| func TestEmitStatusProgress(t *testing.T) { | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	emitter := tasks.NewEventEmitter([]string{}, out) | ||||
| 	out := make(chan *event) | ||||
| 	emitter := newEventEmitter([]string{}, out) | ||||
| 	go func() { | ||||
| 		emitter.EmitStatusProgress(0.7, "foo") | ||||
| 		close(out) | ||||
| @ -55,7 +51,7 @@ func TestEmitStatusProgress(t *testing.T) { | ||||
| 	var found bool | ||||
| 	for ev := range out { | ||||
| 		if ev.Key == "status.progress" { | ||||
| 			evv := ev.Value.(tasks.EventStatusProgress) // panic if not castable | ||||
| 			evv := ev.Value.(eventStatusProgress) // panic if not castable | ||||
| 			if evv.Message == "foo" && evv.Percentage == 0.7 { | ||||
| 				found = true | ||||
| 			} | ||||
| @ -1,40 +0,0 @@ | ||||
| package tasks | ||||
| 
 | ||||
| // EventEmitter emits event on a channel | ||||
| type EventEmitter struct { | ||||
| 	disabled map[string]bool | ||||
| 	out      chan<- *Event | ||||
| } | ||||
| 
 | ||||
| // NewEventEmitter creates a new Emitter | ||||
| func NewEventEmitter(disabledEvents []string, out chan<- *Event) *EventEmitter { | ||||
| 	ee := &EventEmitter{out: out} | ||||
| 	ee.disabled = make(map[string]bool) | ||||
| 	for _, eventname := range disabledEvents { | ||||
| 		ee.disabled[eventname] = true | ||||
| 	} | ||||
| 	return ee | ||||
| } | ||||
| 
 | ||||
| // EmitFailureStartup emits the failureStartup event | ||||
| func (ee *EventEmitter) EmitFailureStartup(failure string) { | ||||
| 	ee.EmitFailureGeneric(failureStartup, failure) | ||||
| } | ||||
| 
 | ||||
| // EmitFailureGeneric emits a failure event | ||||
| func (ee *EventEmitter) EmitFailureGeneric(name, failure string) { | ||||
| 	ee.Emit(name, EventFailure{Failure: failure}) | ||||
| } | ||||
| 
 | ||||
| // EmitStatusProgress emits the status.Progress event | ||||
| func (ee *EventEmitter) EmitStatusProgress(percentage float64, message string) { | ||||
| 	ee.Emit(statusProgress, EventStatusProgress{Message: message, Percentage: percentage}) | ||||
| } | ||||
| 
 | ||||
| // Emit emits the specified event | ||||
| func (ee *EventEmitter) Emit(key string, value interface{}) { | ||||
| 	if ee.disabled[key] == true { | ||||
| 		return | ||||
| 	} | ||||
| 	ee.out <- &Event{Key: key, Value: value} | ||||
| } | ||||
| @ -1,5 +1,4 @@ | ||||
| // Package tasks implements tasks run using the oonimkall API. | ||||
| package tasks | ||||
| package oonimkall | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| @ -36,42 +35,42 @@ const ( | ||||
| 	statusStarted                = "status.started" | ||||
| ) | ||||
| 
 | ||||
| // Run runs the task specified by settings.Name until completion. This is the | ||||
| // run runs the task specified by settings.Name until completion. This is the | ||||
| // top-level API that should be called by oonimkall. | ||||
| func Run(ctx context.Context, settings *Settings, out chan<- *Event) { | ||||
| 	r := NewRunner(settings, out) | ||||
| func run(ctx context.Context, settings *settings, out chan<- *event) { | ||||
| 	r := newRunner(settings, out) | ||||
| 	r.Run(ctx) | ||||
| } | ||||
| 
 | ||||
| // Runner runs a specific task | ||||
| type Runner struct { | ||||
| 	emitter             *EventEmitter | ||||
| // runner runs a specific task | ||||
| type runner struct { | ||||
| 	emitter             *eventEmitter | ||||
| 	maybeLookupLocation func(*engine.Session) error | ||||
| 	out                 chan<- *Event | ||||
| 	settings            *Settings | ||||
| 	out                 chan<- *event | ||||
| 	settings            *settings | ||||
| } | ||||
| 
 | ||||
| // NewRunner creates a new task runner | ||||
| func NewRunner(settings *Settings, out chan<- *Event) *Runner { | ||||
| 	return &Runner{ | ||||
| 		emitter:  NewEventEmitter(settings.DisabledEvents, out), | ||||
| // newRunner creates a new task runner | ||||
| func newRunner(settings *settings, out chan<- *event) *runner { | ||||
| 	return &runner{ | ||||
| 		emitter:  newEventEmitter(settings.DisabledEvents, out), | ||||
| 		out:      out, | ||||
| 		settings: settings, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // FailureInvalidVersion is the failure returned when Version is invalid | ||||
| const FailureInvalidVersion = "invalid Settings.Version number" | ||||
| // failureInvalidVersion is the failure returned when Version is invalid | ||||
| const failureInvalidVersion = "invalid Settings.Version number" | ||||
| 
 | ||||
| func (r *Runner) hasUnsupportedSettings(logger *ChanLogger) bool { | ||||
| func (r *runner) hasUnsupportedSettings(logger *chanLogger) bool { | ||||
| 	if r.settings.Version < 1 { | ||||
| 		r.emitter.EmitFailureStartup(FailureInvalidVersion) | ||||
| 		r.emitter.EmitFailureStartup(failureInvalidVersion) | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (r *Runner) newsession(ctx context.Context, logger *ChanLogger) (*engine.Session, error) { | ||||
| func (r *runner) newsession(ctx context.Context, logger *chanLogger) (*engine.Session, error) { | ||||
| 	kvstore, err := kvstore.NewFS(r.settings.StateDir) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @ -106,7 +105,7 @@ func (r *Runner) newsession(ctx context.Context, logger *ChanLogger) (*engine.Se | ||||
| 	return engine.NewSession(ctx, config) | ||||
| } | ||||
| 
 | ||||
| func (r *Runner) contextForExperiment( | ||||
| func (r *runner) contextForExperiment( | ||||
| 	ctx context.Context, builder *engine.ExperimentBuilder, | ||||
| ) context.Context { | ||||
| 	if builder.Interruptible() { | ||||
| @ -116,11 +115,11 @@ func (r *Runner) contextForExperiment( | ||||
| } | ||||
| 
 | ||||
| type runnerCallbacks struct { | ||||
| 	emitter *EventEmitter | ||||
| 	emitter *eventEmitter | ||||
| } | ||||
| 
 | ||||
| func (cb *runnerCallbacks) OnProgress(percentage float64, message string) { | ||||
| 	cb.emitter.Emit(statusProgress, EventStatusProgress{ | ||||
| 	cb.emitter.Emit(statusProgress, eventStatusProgress{ | ||||
| 		Percentage: 0.4 + (percentage * 0.6), // open report is 40% | ||||
| 		Message:    message, | ||||
| 	}) | ||||
| @ -129,8 +128,8 @@ func (cb *runnerCallbacks) OnProgress(percentage float64, message string) { | ||||
| // Run runs the runner until completion. The context argument controls | ||||
| // when to stop when processing multiple inputs, as well as when to stop | ||||
| // experiments explicitly marked as interruptible. | ||||
| func (r *Runner) Run(ctx context.Context) { | ||||
| 	logger := NewChanLogger(r.emitter, r.settings.LogLevel, r.out) | ||||
| func (r *runner) Run(ctx context.Context) { | ||||
| 	logger := newChanLogger(r.emitter, r.settings.LogLevel, r.out) | ||||
| 	r.emitter.Emit(statusQueued, eventEmpty{}) | ||||
| 	if r.hasUnsupportedSettings(logger) { | ||||
| 		return | ||||
| @ -1,4 +1,4 @@ | ||||
| package tasks_test | ||||
| package oonimkall | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| @ -8,8 +8,6 @@ import ( | ||||
| 	"sync" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/ooni/probe-cli/v3/pkg/oonimkall/internal/tasks" | ||||
| ) | ||||
| 
 | ||||
| func TestRunnerMaybeLookupBackendsFailure(t *testing.T) { | ||||
| @ -17,11 +15,11 @@ func TestRunnerMaybeLookupBackendsFailure(t *testing.T) { | ||||
| 		w.WriteHeader(500) | ||||
| 	})) | ||||
| 	defer server.Close() | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		Name:      "Example", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			ProbeServicesBaseURL: server.URL, | ||||
| 			SoftwareName:         "oonimkall-test", | ||||
| 			SoftwareVersion:      "0.1.0", | ||||
| @ -30,14 +28,14 @@ func TestRunnerMaybeLookupBackendsFailure(t *testing.T) { | ||||
| 		Version:  1, | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var failures []string | ||||
| 	for ev := range out { | ||||
| 		switch ev.Key { | ||||
| 		case "failure.startup": | ||||
| 			failure := ev.Value.(tasks.EventFailure).Failure | ||||
| 			failure := ev.Value.(eventFailure).Failure | ||||
| 			failures = append(failures, failure) | ||||
| 		case "status.queued", "status.started", "log", "status.end": | ||||
| 		default: | ||||
| @ -71,11 +69,11 @@ func TestRunnerOpenReportFailure(t *testing.T) { | ||||
| 		w.WriteHeader(500) | ||||
| 	})) | ||||
| 	defer server.Close() | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		Name:      "Example", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			ProbeServicesBaseURL: server.URL, | ||||
| 			SoftwareName:         "oonimkall-test", | ||||
| 			SoftwareVersion:      "0.1.0", | ||||
| @ -91,7 +89,7 @@ func TestRunnerOpenReportFailure(t *testing.T) { | ||||
| 			case "failure.report_create": | ||||
| 				seen++ | ||||
| 			case "status.progress": | ||||
| 				evv := ev.Value.(tasks.EventStatusProgress) | ||||
| 				evv := ev.Value.(eventStatusProgress) | ||||
| 				if evv.Percentage >= 0.4 { | ||||
| 					panic(fmt.Sprintf("too much progress: %+v", ev)) | ||||
| 				} | ||||
| @ -103,7 +101,7 @@ func TestRunnerOpenReportFailure(t *testing.T) { | ||||
| 		} | ||||
| 		seench <- seen | ||||
| 	}() | ||||
| 	tasks.Run(context.Background(), settings, out) | ||||
| 	run(context.Background(), settings, out) | ||||
| 	close(out) | ||||
| 	if n := <-seench; n != 1 { | ||||
| 		t.Fatal("unexpected number of events") | ||||
| @ -114,12 +112,12 @@ func TestRunnerGood(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "Example", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| 		}, | ||||
| @ -127,7 +125,7 @@ func TestRunnerGood(t *testing.T) { | ||||
| 		Version:  1, | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var found bool | ||||
| @ -145,32 +143,32 @@ func TestRunnerWithUnsupportedSettings(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "Example", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| 		}, | ||||
| 		StateDir: "../../testdata/oonimkall/state", | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var failures []string | ||||
| 	for ev := range out { | ||||
| 		if ev.Key == "failure.startup" { | ||||
| 			failure := ev.Value.(tasks.EventFailure).Failure | ||||
| 			failure := ev.Value.(eventFailure).Failure | ||||
| 			failures = append(failures, failure) | ||||
| 		} | ||||
| 	} | ||||
| 	if len(failures) != 1 { | ||||
| 		t.Fatal("invalid number of failures") | ||||
| 	} | ||||
| 	if failures[0] != tasks.FailureInvalidVersion { | ||||
| 	if failures[0] != failureInvalidVersion { | ||||
| 		t.Fatal("not the failure we expected") | ||||
| 	} | ||||
| } | ||||
| @ -179,12 +177,12 @@ func TestRunnerWithInvalidKVStorePath(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "Example", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| 		}, | ||||
| @ -192,13 +190,13 @@ func TestRunnerWithInvalidKVStorePath(t *testing.T) { | ||||
| 		Version:  1, | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var failures []string | ||||
| 	for ev := range out { | ||||
| 		if ev.Key == "failure.startup" { | ||||
| 			failure := ev.Value.(tasks.EventFailure).Failure | ||||
| 			failure := ev.Value.(eventFailure).Failure | ||||
| 			failures = append(failures, failure) | ||||
| 		} | ||||
| 	} | ||||
| @ -214,12 +212,12 @@ func TestRunnerWithInvalidExperimentName(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "Nonexistent", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| 		}, | ||||
| @ -227,13 +225,13 @@ func TestRunnerWithInvalidExperimentName(t *testing.T) { | ||||
| 		Version:  1, | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var failures []string | ||||
| 	for ev := range out { | ||||
| 		if ev.Key == "failure.startup" { | ||||
| 			failure := ev.Value.(tasks.EventFailure).Failure | ||||
| 			failure := ev.Value.(eventFailure).Failure | ||||
| 			failures = append(failures, failure) | ||||
| 		} | ||||
| 	} | ||||
| @ -249,12 +247,12 @@ func TestRunnerWithMissingInput(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "ExampleWithInput", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| 		}, | ||||
| @ -262,13 +260,13 @@ func TestRunnerWithMissingInput(t *testing.T) { | ||||
| 		Version:  1, | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var failures []string | ||||
| 	for ev := range out { | ||||
| 		if ev.Key == "failure.startup" { | ||||
| 			failure := ev.Value.(tasks.EventFailure).Failure | ||||
| 			failure := ev.Value.(eventFailure).Failure | ||||
| 			failures = append(failures, failure) | ||||
| 		} | ||||
| 	} | ||||
| @ -284,13 +282,13 @@ func TestRunnerWithMaxRuntime(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		Inputs:    []string{"a", "b", "c", "d", "e", "f", "g", "h", "i"}, | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "ExampleWithInput", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			MaxRuntime:      1, | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| @ -300,7 +298,7 @@ func TestRunnerWithMaxRuntime(t *testing.T) { | ||||
| 	} | ||||
| 	begin := time.Now() | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var found bool | ||||
| @ -320,7 +318,7 @@ func TestRunnerWithMaxRuntime(t *testing.T) { | ||||
| 	// 1. https://github.com/ooni/probe-cli/v3/internal/engine/pull/588/checks?check_run_id=667263788 | ||||
| 	// | ||||
| 	// 2. https://github.com/ooni/probe-cli/v3/internal/engine/pull/588/checks?check_run_id=667263855 | ||||
| 	if time.Now().Sub(begin) > 10*time.Second { | ||||
| 	if time.Since(begin) > 10*time.Second { | ||||
| 		t.Fatal("expected shorter runtime") | ||||
| 	} | ||||
| } | ||||
| @ -329,13 +327,13 @@ func TestRunnerWithMaxRuntimeNonInterruptible(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		Inputs:    []string{"a", "b", "c", "d", "e", "f", "g", "h", "i"}, | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "ExampleWithInputNonInterruptible", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			MaxRuntime:      1, | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| @ -345,7 +343,7 @@ func TestRunnerWithMaxRuntimeNonInterruptible(t *testing.T) { | ||||
| 	} | ||||
| 	begin := time.Now() | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var found bool | ||||
| @ -365,7 +363,7 @@ func TestRunnerWithMaxRuntimeNonInterruptible(t *testing.T) { | ||||
| 	// 1. https://github.com/ooni/probe-cli/v3/internal/engine/pull/588/checks?check_run_id=667263788 | ||||
| 	// | ||||
| 	// 2. https://github.com/ooni/probe-cli/v3/internal/engine/pull/588/checks?check_run_id=667263855 | ||||
| 	if time.Now().Sub(begin) > 10*time.Second { | ||||
| 	if time.Since(begin) > 10*time.Second { | ||||
| 		t.Fatal("expected shorter runtime") | ||||
| 	} | ||||
| } | ||||
| @ -374,13 +372,13 @@ func TestRunnerWithFailedMeasurement(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *tasks.Event) | ||||
| 	settings := &tasks.Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		Inputs:    []string{"a", "b", "c", "d", "e", "f", "g", "h", "i"}, | ||||
| 		LogLevel:  "DEBUG", | ||||
| 		Name:      "ExampleWithFailure", | ||||
| 		Options: tasks.SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			MaxRuntime:      1, | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| @ -389,7 +387,7 @@ func TestRunnerWithFailedMeasurement(t *testing.T) { | ||||
| 		Version:  1, | ||||
| 	} | ||||
| 	go func() { | ||||
| 		tasks.Run(context.Background(), settings, out) | ||||
| 		run(context.Background(), settings, out) | ||||
| 		close(out) | ||||
| 	}() | ||||
| 	var found bool | ||||
| @ -1,4 +1,4 @@ | ||||
| package tasks | ||||
| package oonimkall | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| @ -32,11 +32,11 @@ func TestRunnerMaybeLookupLocationFailure(t *testing.T) { | ||||
| 		// TODO(https://github.com/ooni/probe-cli/pull/518) | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	out := make(chan *Event) | ||||
| 	settings := &Settings{ | ||||
| 	out := make(chan *event) | ||||
| 	settings := &settings{ | ||||
| 		AssetsDir: "../../testdata/oonimkall/assets", | ||||
| 		Name:      "Example", | ||||
| 		Options: SettingsOptions{ | ||||
| 		Options: settingsOptions{ | ||||
| 			SoftwareName:    "oonimkall-test", | ||||
| 			SoftwareVersion: "0.1.0", | ||||
| 		}, | ||||
| @ -52,7 +52,7 @@ func TestRunnerMaybeLookupLocationFailure(t *testing.T) { | ||||
| 				"failure.cc_lookup", "failure.resolver_lookup": | ||||
| 				seen++ | ||||
| 			case "status.progress": | ||||
| 				evv := ev.Value.(EventStatusProgress) | ||||
| 				evv := ev.Value.(eventStatusProgress) | ||||
| 				if evv.Percentage >= 0.2 { | ||||
| 					panic(fmt.Sprintf("too much progress: %+v", ev)) | ||||
| 				} | ||||
| @ -64,7 +64,7 @@ func TestRunnerMaybeLookupLocationFailure(t *testing.T) { | ||||
| 		seench <- seen | ||||
| 	}() | ||||
| 	expected := errors.New("mocked error") | ||||
| 	r := NewRunner(settings, out) | ||||
| 	r := newRunner(settings, out) | ||||
| 	r.maybeLookupLocation = func(*engine.Session) error { | ||||
| 		return expected | ||||
| 	} | ||||
| @ -1,9 +1,9 @@ | ||||
| package tasks | ||||
| package oonimkall | ||||
| 
 | ||||
| // Settings contains settings for a task. This structure derives from | ||||
| // the one described by MK v0.10.9 FFI API (https://git.io/Jv4Rv), yet | ||||
| // since 2020-12-03 we're not backwards compatible anymore. | ||||
| type Settings struct { | ||||
| type settings struct { | ||||
| 	// Annotations contains the annotations to be added | ||||
| 	// to every measurements performed by the task. | ||||
| 	Annotations map[string]string `json:"annotations,omitempty"` | ||||
| @ -30,7 +30,7 @@ type Settings struct { | ||||
| 	Name string `json:"name"` | ||||
| 
 | ||||
| 	// Options contains the task options. | ||||
| 	Options SettingsOptions `json:"options"` | ||||
| 	Options settingsOptions `json:"options"` | ||||
| 
 | ||||
| 	// Proxy allows you to optionally force a specific proxy | ||||
| 	// rather than using no proxy (the default). | ||||
| @ -66,8 +66,8 @@ type Settings struct { | ||||
| 	Version int64 `json:"version"` | ||||
| } | ||||
| 
 | ||||
| // SettingsOptions contains the settings options | ||||
| type SettingsOptions struct { | ||||
| // settingsOptions contains the settings options | ||||
| type settingsOptions struct { | ||||
| 	// MaxRuntime is the maximum runtime expressed in seconds. A negative | ||||
| 	// value for this field disables the maximum runtime. Using | ||||
| 	// a zero value will also mean disabled. This is not the | ||||
| @ -45,7 +45,6 @@ import ( | ||||
| 
 | ||||
| 	"github.com/ooni/probe-cli/v3/internal/atomicx" | ||||
| 	"github.com/ooni/probe-cli/v3/internal/runtimex" | ||||
| 	"github.com/ooni/probe-cli/v3/pkg/oonimkall/internal/tasks" | ||||
| ) | ||||
| 
 | ||||
| // Task is an asynchronous task running an experiment. It mimics the | ||||
| @ -63,13 +62,13 @@ type Task struct { | ||||
| 	cancel    context.CancelFunc | ||||
| 	isdone    *atomicx.Int64 | ||||
| 	isstopped *atomicx.Int64 | ||||
| 	out       chan *tasks.Event | ||||
| 	out       chan *event | ||||
| } | ||||
| 
 | ||||
| // StartTask starts an asynchronous task. The input argument is a | ||||
| // serialized JSON conforming to MK v0.10.9's API. | ||||
| func StartTask(input string) (*Task, error) { | ||||
| 	var settings tasks.Settings | ||||
| 	var settings settings | ||||
| 	if err := json.Unmarshal([]byte(input), &settings); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -79,12 +78,12 @@ func StartTask(input string) (*Task, error) { | ||||
| 		cancel:    cancel, | ||||
| 		isdone:    &atomicx.Int64{}, | ||||
| 		isstopped: &atomicx.Int64{}, | ||||
| 		out:       make(chan *tasks.Event, bufsiz), | ||||
| 		out:       make(chan *event, bufsiz), | ||||
| 	} | ||||
| 	go func() { | ||||
| 		defer close(task.out) | ||||
| 		defer task.isstopped.Add(1) | ||||
| 		tasks.Run(ctx, &settings, task.out) | ||||
| 		run(ctx, &settings, task.out) | ||||
| 	}() | ||||
| 	return task, nil | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| package oonimkall_test | ||||
| package oonimkall | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| @ -9,8 +9,6 @@ import ( | ||||
| 
 | ||||
| 	"github.com/google/go-cmp/cmp" | ||||
| 	"github.com/ooni/probe-cli/v3/internal/engine/model" | ||||
| 	"github.com/ooni/probe-cli/v3/pkg/oonimkall" | ||||
| 	"github.com/ooni/probe-cli/v3/pkg/oonimkall/internal/tasks" | ||||
| ) | ||||
| 
 | ||||
| type eventlike struct { | ||||
| @ -22,7 +20,7 @@ func TestGood(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"log_level": "DEBUG", | ||||
| 		"name": "Example", | ||||
| @ -69,7 +67,7 @@ func TestWithMeasurementFailure(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"log_level": "DEBUG", | ||||
| 		"name": "ExampleWithFailure", | ||||
| @ -98,7 +96,7 @@ func TestWithMeasurementFailure(t *testing.T) { | ||||
| } | ||||
| 
 | ||||
| func TestInvalidJSON(t *testing.T) { | ||||
| 	task, err := oonimkall.StartTask(`{`) | ||||
| 	task, err := StartTask(`{`) | ||||
| 	var syntaxerr *json.SyntaxError | ||||
| 	if !errors.As(err, &syntaxerr) { | ||||
| 		t.Fatal("not the expected error") | ||||
| @ -109,7 +107,7 @@ func TestInvalidJSON(t *testing.T) { | ||||
| } | ||||
| 
 | ||||
| func TestUnsupportedSetting(t *testing.T) { | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"log_level": "DEBUG", | ||||
| 		"name": "Example", | ||||
| @ -130,7 +128,7 @@ func TestUnsupportedSetting(t *testing.T) { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if event.Key == "failure.startup" { | ||||
| 			if strings.Contains(eventstr, tasks.FailureInvalidVersion) { | ||||
| 			if strings.Contains(eventstr, failureInvalidVersion) { | ||||
| 				seen = true | ||||
| 			} | ||||
| 		} | ||||
| @ -141,7 +139,7 @@ func TestUnsupportedSetting(t *testing.T) { | ||||
| } | ||||
| 
 | ||||
| func TestEmptyStateDir(t *testing.T) { | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"log_level": "DEBUG", | ||||
| 		"name": "Example", | ||||
| @ -173,7 +171,7 @@ func TestEmptyStateDir(t *testing.T) { | ||||
| } | ||||
| 
 | ||||
| func TestUnknownExperiment(t *testing.T) { | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"log_level": "DEBUG", | ||||
| 		"name": "Antani", | ||||
| @ -209,7 +207,7 @@ func TestInputIsRequired(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"log_level": "DEBUG", | ||||
| 		"name": "ExampleWithInput", | ||||
| @ -246,7 +244,7 @@ func TestMaxRuntime(t *testing.T) { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	begin := time.Now() | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"inputs": ["a", "b", "c"], | ||||
| 		"name": "ExampleWithInput", | ||||
| @ -293,7 +291,7 @@ func TestInterruptExampleWithInput(t *testing.T) { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	t.Skip("Skipping broken test; see https://github.com/ooni/probe-cli/v3/internal/engine/issues/992") | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"inputs": [ | ||||
| 			"http://www.kernel.org/", | ||||
| @ -360,7 +358,7 @@ func TestInterruptNdt7(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"name": "Ndt7", | ||||
| 		"options": { | ||||
| @ -417,7 +415,7 @@ func TestCountBytesForExample(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"name": "Example", | ||||
| 		"options": { | ||||
| @ -457,7 +455,7 @@ func TestPrivacyAndScrubbing(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 			"assets_dir": "../testdata/oonimkall/assets", | ||||
| 			"name": "Example", | ||||
| 			"options": { | ||||
| @ -500,7 +498,7 @@ func TestNonblock(t *testing.T) { | ||||
| 	if testing.Short() { | ||||
| 		t.Skip("skip test in short mode") | ||||
| 	} | ||||
| 	task, err := oonimkall.StartTask(`{ | ||||
| 	task, err := StartTask(`{ | ||||
| 		"assets_dir": "../testdata/oonimkall/assets", | ||||
| 		"name": "Example", | ||||
| 		"options": { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user