1package engine
2
3import (
4	"time"
5
6	"github.com/ooni/probe-engine/experiment/dash"
7	"github.com/ooni/probe-engine/experiment/dnscheck"
8	"github.com/ooni/probe-engine/experiment/example"
9	"github.com/ooni/probe-engine/experiment/fbmessenger"
10	"github.com/ooni/probe-engine/experiment/hhfm"
11	"github.com/ooni/probe-engine/experiment/hirl"
12	"github.com/ooni/probe-engine/experiment/httphostheader"
13	"github.com/ooni/probe-engine/experiment/ndt7"
14	"github.com/ooni/probe-engine/experiment/psiphon"
15	"github.com/ooni/probe-engine/experiment/riseupvpn"
16	"github.com/ooni/probe-engine/experiment/run"
17	"github.com/ooni/probe-engine/experiment/sniblocking"
18	"github.com/ooni/probe-engine/experiment/stunreachability"
19	"github.com/ooni/probe-engine/experiment/telegram"
20	"github.com/ooni/probe-engine/experiment/tlstool"
21	"github.com/ooni/probe-engine/experiment/tor"
22	"github.com/ooni/probe-engine/experiment/urlgetter"
23	"github.com/ooni/probe-engine/experiment/webconnectivity"
24	"github.com/ooni/probe-engine/experiment/whatsapp"
25)
26
27var experimentsByName = map[string]func(*Session) *ExperimentBuilder{
28	"dash": func(session *Session) *ExperimentBuilder {
29		return &ExperimentBuilder{
30			build: func(config interface{}) *Experiment {
31				return NewExperiment(session, dash.NewExperimentMeasurer(
32					*config.(*dash.Config),
33				))
34			},
35			config:        &dash.Config{},
36			interruptible: true,
37			inputPolicy:   InputNone,
38		}
39	},
40
41	"dnscheck": func(session *Session) *ExperimentBuilder {
42		return &ExperimentBuilder{
43			build: func(config interface{}) *Experiment {
44				return NewExperiment(session, dnscheck.NewExperimentMeasurer(
45					*config.(*dnscheck.Config),
46				))
47			},
48			config:      &dnscheck.Config{},
49			inputPolicy: InputStrictlyRequired,
50		}
51	},
52
53	"example": func(session *Session) *ExperimentBuilder {
54		return &ExperimentBuilder{
55			build: func(config interface{}) *Experiment {
56				return NewExperiment(session, example.NewExperimentMeasurer(
57					*config.(*example.Config), "example",
58				))
59			},
60			config: &example.Config{
61				Message:   "Good day from the example experiment!",
62				SleepTime: int64(time.Second),
63			},
64			interruptible: true,
65			inputPolicy:   InputNone,
66		}
67	},
68
69	"example_with_input": func(session *Session) *ExperimentBuilder {
70		return &ExperimentBuilder{
71			build: func(config interface{}) *Experiment {
72				return NewExperiment(session, example.NewExperimentMeasurer(
73					*config.(*example.Config), "example_with_input",
74				))
75			},
76			config: &example.Config{
77				Message:   "Good day from the example with input experiment!",
78				SleepTime: int64(time.Second),
79			},
80			interruptible: true,
81			inputPolicy:   InputStrictlyRequired,
82		}
83	},
84
85	// TODO(bassosimone): when we can set experiment options using the JSON
86	// we need to get rid of all these multiple experiments.
87	//
88	// See https://github.com/ooni/probe-engine/issues/413
89	"example_with_input_non_interruptible": func(session *Session) *ExperimentBuilder {
90		return &ExperimentBuilder{
91			build: func(config interface{}) *Experiment {
92				return NewExperiment(session, example.NewExperimentMeasurer(
93					*config.(*example.Config), "example_with_input_non_interruptible",
94				))
95			},
96			config: &example.Config{
97				Message:   "Good day from the example with input experiment!",
98				SleepTime: int64(time.Second),
99			},
100			interruptible: false,
101			inputPolicy:   InputStrictlyRequired,
102		}
103	},
104
105	"example_with_failure": func(session *Session) *ExperimentBuilder {
106		return &ExperimentBuilder{
107			build: func(config interface{}) *Experiment {
108				return NewExperiment(session, example.NewExperimentMeasurer(
109					*config.(*example.Config), "example_with_failure",
110				))
111			},
112			config: &example.Config{
113				Message:     "Good day from the example with failure experiment!",
114				ReturnError: true,
115				SleepTime:   int64(time.Second),
116			},
117			interruptible: true,
118			inputPolicy:   InputNone,
119		}
120	},
121
122	"facebook_messenger": func(session *Session) *ExperimentBuilder {
123		return &ExperimentBuilder{
124			build: func(config interface{}) *Experiment {
125				return NewExperiment(session, fbmessenger.NewExperimentMeasurer(
126					*config.(*fbmessenger.Config),
127				))
128			},
129			config:      &fbmessenger.Config{},
130			inputPolicy: InputNone,
131		}
132	},
133
134	"http_header_field_manipulation": func(session *Session) *ExperimentBuilder {
135		return &ExperimentBuilder{
136			build: func(config interface{}) *Experiment {
137				return NewExperiment(session, hhfm.NewExperimentMeasurer(
138					*config.(*hhfm.Config),
139				))
140			},
141			config:      &hhfm.Config{},
142			inputPolicy: InputNone,
143		}
144	},
145
146	"http_host_header": func(session *Session) *ExperimentBuilder {
147		return &ExperimentBuilder{
148			build: func(config interface{}) *Experiment {
149				return NewExperiment(session, httphostheader.NewExperimentMeasurer(
150					*config.(*httphostheader.Config),
151				))
152			},
153			config:      &httphostheader.Config{},
154			inputPolicy: InputOrQueryTestLists,
155		}
156	},
157
158	"http_invalid_request_line": func(session *Session) *ExperimentBuilder {
159		return &ExperimentBuilder{
160			build: func(config interface{}) *Experiment {
161				return NewExperiment(session, hirl.NewExperimentMeasurer(
162					*config.(*hirl.Config),
163				))
164			},
165			config:      &hirl.Config{},
166			inputPolicy: InputNone,
167		}
168	},
169
170	"ndt": func(session *Session) *ExperimentBuilder {
171		return &ExperimentBuilder{
172			build: func(config interface{}) *Experiment {
173				return NewExperiment(session, ndt7.NewExperimentMeasurer(
174					*config.(*ndt7.Config),
175				))
176			},
177			config:        &ndt7.Config{},
178			interruptible: true,
179			inputPolicy:   InputNone,
180		}
181	},
182
183	"psiphon": func(session *Session) *ExperimentBuilder {
184		return &ExperimentBuilder{
185			build: func(config interface{}) *Experiment {
186				return NewExperiment(session, psiphon.NewExperimentMeasurer(
187					*config.(*psiphon.Config),
188				))
189			},
190			config:      &psiphon.Config{},
191			inputPolicy: InputOptional,
192		}
193	},
194
195	"riseupvpn": func(session *Session) *ExperimentBuilder {
196		return &ExperimentBuilder{
197			build: func(config interface{}) *Experiment {
198				return NewExperiment(session, riseupvpn.NewExperimentMeasurer(
199					*config.(*riseupvpn.Config),
200				))
201			},
202			config:      &riseupvpn.Config{},
203			inputPolicy: InputNone,
204		}
205	},
206
207	"run": func(session *Session) *ExperimentBuilder {
208		return &ExperimentBuilder{
209			build: func(config interface{}) *Experiment {
210				return NewExperiment(session, run.NewExperimentMeasurer(
211					*config.(*run.Config),
212				))
213			},
214			config:      &run.Config{},
215			inputPolicy: InputStrictlyRequired,
216		}
217	},
218
219	"sni_blocking": func(session *Session) *ExperimentBuilder {
220		return &ExperimentBuilder{
221			build: func(config interface{}) *Experiment {
222				return NewExperiment(session, sniblocking.NewExperimentMeasurer(
223					*config.(*sniblocking.Config),
224				))
225			},
226			config:      &sniblocking.Config{},
227			inputPolicy: InputOrQueryTestLists,
228		}
229	},
230
231	"stun_reachability": func(session *Session) *ExperimentBuilder {
232		return &ExperimentBuilder{
233			build: func(config interface{}) *Experiment {
234				return NewExperiment(session, stunreachability.NewExperimentMeasurer(
235					*config.(*stunreachability.Config),
236				))
237			},
238			config:      &stunreachability.Config{},
239			inputPolicy: InputOptional,
240		}
241	},
242
243	"telegram": func(session *Session) *ExperimentBuilder {
244		return &ExperimentBuilder{
245			build: func(config interface{}) *Experiment {
246				return NewExperiment(session, telegram.NewExperimentMeasurer(
247					*config.(*telegram.Config),
248				))
249			},
250			config:      &telegram.Config{},
251			inputPolicy: InputNone,
252		}
253	},
254
255	"tlstool": func(session *Session) *ExperimentBuilder {
256		return &ExperimentBuilder{
257			build: func(config interface{}) *Experiment {
258				return NewExperiment(session, tlstool.NewExperimentMeasurer(
259					*config.(*tlstool.Config),
260				))
261			},
262			config:      &tlstool.Config{},
263			inputPolicy: InputOrQueryTestLists,
264		}
265	},
266
267	"tor": func(session *Session) *ExperimentBuilder {
268		return &ExperimentBuilder{
269			build: func(config interface{}) *Experiment {
270				return NewExperiment(session, tor.NewExperimentMeasurer(
271					*config.(*tor.Config),
272				))
273			},
274			config:      &tor.Config{},
275			inputPolicy: InputNone,
276		}
277	},
278
279	"urlgetter": func(session *Session) *ExperimentBuilder {
280		return &ExperimentBuilder{
281			build: func(config interface{}) *Experiment {
282				return NewExperiment(session, urlgetter.NewExperimentMeasurer(
283					*config.(*urlgetter.Config),
284				))
285			},
286			config:      &urlgetter.Config{},
287			inputPolicy: InputStrictlyRequired,
288		}
289	},
290
291	"web_connectivity": func(session *Session) *ExperimentBuilder {
292		return &ExperimentBuilder{
293			build: func(config interface{}) *Experiment {
294				return NewExperiment(session, webconnectivity.NewExperimentMeasurer(
295					*config.(*webconnectivity.Config),
296				))
297			},
298			config:      &webconnectivity.Config{},
299			inputPolicy: InputOrQueryTestLists,
300		}
301	},
302
303	"whatsapp": func(session *Session) *ExperimentBuilder {
304		return &ExperimentBuilder{
305			build: func(config interface{}) *Experiment {
306				return NewExperiment(session, whatsapp.NewExperimentMeasurer(
307					*config.(*whatsapp.Config),
308				))
309			},
310			config:      &whatsapp.Config{},
311			inputPolicy: InputNone,
312		}
313	},
314}
315
316// AllExperiments returns the name of all experiments
317func AllExperiments() []string {
318	var names []string
319	for key := range experimentsByName {
320		names = append(names, key)
321	}
322	return names
323}
324