github.com/iter8-tools/iter8@v1.1.2/base/experiment_test.go (about) 1 package base 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "net/http" 8 "os" 9 "testing" 10 11 "fortio.org/fortio/fhttp" 12 "github.com/stretchr/testify/assert" 13 "sigs.k8s.io/yaml" 14 ) 15 16 func TestReadExperiment(t *testing.T) { 17 _ = os.Chdir(t.TempDir()) 18 19 b, err := os.ReadFile(CompletePath("../testdata", "experiment.yaml")) 20 assert.NoError(t, err) 21 e := &Experiment{} 22 err = yaml.Unmarshal(b, e) 23 assert.NoError(t, err) 24 assert.Equal(t, 1, len(e.Spec)) 25 26 b, err = os.ReadFile(CompletePath("../testdata", "experiment_grpc.yaml")) 27 assert.NoError(t, err) 28 e = &Experiment{} 29 err = yaml.Unmarshal(b, e) 30 assert.NoError(t, err) 31 assert.Equal(t, 1, len(e.Spec)) 32 } 33 34 func TestRunningTasks(t *testing.T) { 35 // define METRICS_SERVER_URL 36 metricsServerURL := "http://iter8.default:8080" 37 err := os.Setenv(MetricsServerURL, metricsServerURL) 38 assert.NoError(t, err) 39 40 // create and configure HTTP endpoint for testing 41 mux, addr := fhttp.DynamicHTTPServer(false) 42 url := fmt.Sprintf("http://127.0.0.1:%d/get", addr.Port) 43 var verifyHandlerCalled bool 44 mux.HandleFunc("/get", GetTrackingHandler(&verifyHandlerCalled)) 45 46 _ = os.Chdir(t.TempDir()) 47 48 // valid collect task... should succeed 49 ct := &collectHTTPTask{ 50 TaskMeta: TaskMeta{ 51 Task: StringPointer(CollectHTTPTaskName), 52 }, 53 With: collectHTTPInputs{ 54 endpoint: endpoint{ 55 Duration: StringPointer("1s"), 56 Headers: map[string]string{}, 57 URL: url, 58 }, 59 }, 60 } 61 62 exp := &Experiment{ 63 Spec: []Task{ct}, 64 Result: &ExperimentResult{}, 65 Metadata: ExperimentMetadata{ 66 Name: myName, 67 Namespace: myNamespace, 68 }, 69 } 70 exp.initResults(1) 71 err = ct.run(exp) 72 assert.NoError(t, err) 73 assert.Equal(t, exp.Result.Insights.NumVersions, 1) 74 // sanity check -- handler was called 75 assert.True(t, verifyHandlerCalled) 76 } 77 78 func TestRunExperiment(t *testing.T) { 79 // define METRICS_SERVER_URL 80 metricsServerURL := "http://iter8.default:8080" 81 err := os.Setenv(MetricsServerURL, metricsServerURL) 82 assert.NoError(t, err) 83 84 // create and configure HTTP endpoint for testing 85 mux, addr := fhttp.DynamicHTTPServer(false) 86 url := fmt.Sprintf("http://127.0.0.1:%d/get", addr.Port) 87 var verifyHandlerCalled bool 88 mux.HandleFunc("/get", GetTrackingHandler(&verifyHandlerCalled)) 89 90 // mock metrics server 91 StartHTTPMock(t) 92 metricsServerCalled := false 93 MockMetricsServer(MockMetricsServerInput{ 94 MetricsServerURL: metricsServerURL, 95 ExperimentResultCallback: func(req *http.Request) { 96 metricsServerCalled = true 97 98 // check query parameters 99 assert.Equal(t, myName, req.URL.Query().Get("test")) 100 assert.Equal(t, myNamespace, req.URL.Query().Get("namespace")) 101 102 // check payload 103 body, err := io.ReadAll(req.Body) 104 assert.NoError(t, err) 105 assert.NotNil(t, body) 106 107 // check payload content 108 bodyExperimentResult := ExperimentResult{} 109 err = json.Unmarshal(body, &bodyExperimentResult) 110 assert.NoError(t, err) 111 assert.NotNil(t, body) 112 }, 113 }) 114 115 _ = os.Chdir(t.TempDir()) 116 117 // create experiment.yaml 118 CreateExperimentYaml(t, CompletePath("../testdata", "experiment.tpl"), url, "experiment.yaml") 119 b, err := os.ReadFile("experiment.yaml") 120 121 assert.NoError(t, err) 122 e := &Experiment{} 123 err = yaml.Unmarshal(b, e) 124 assert.NoError(t, err) 125 assert.Equal(t, 1, len(e.Spec)) 126 127 err = RunExperiment(&mockDriver{e}) 128 assert.NoError(t, err) 129 assert.True(t, metricsServerCalled) 130 // sanity check -- handler was called 131 assert.True(t, verifyHandlerCalled) 132 133 assert.True(t, e.Completed()) 134 assert.True(t, e.NoFailure()) 135 } 136 137 func TestFailExperiment(t *testing.T) { 138 _ = os.Chdir(t.TempDir()) 139 exp := Experiment{ 140 Spec: ExperimentSpec{}, 141 } 142 exp.initResults(1) 143 144 exp.failExperiment() 145 assert.False(t, exp.NoFailure()) 146 } 147 148 func TestUnmarshalJSON(t *testing.T) { 149 tests := []struct { 150 specBytes string 151 errMessage string 152 }{ 153 { 154 specBytes: `[{"task":"ready"}]`, 155 }, 156 { 157 specBytes: `[{"task":"http"}]`, 158 }, 159 { 160 specBytes: `[{"task":"grpc"}]`, 161 }, 162 { 163 specBytes: `[{"task":"notify"}]`, 164 }, 165 } 166 167 for _, test := range tests { 168 exp := ExperimentSpec{} 169 err := exp.UnmarshalJSON([]byte(test.specBytes)) 170 assert.NoError(t, err) 171 } 172 } 173 174 func TestUnmarshalJSONError(t *testing.T) { 175 tests := []struct { 176 specBytes string 177 errMessage string 178 }{ 179 { 180 specBytes: "hello world", 181 errMessage: `invalid character 'h' looking for beginning of value`, 182 }, 183 { 184 specBytes: "[{}]", 185 errMessage: `invalid task found without a task name or a run command`, 186 }, 187 { 188 specBytes: `[{"task":"hello world"}]`, 189 errMessage: `unknown task: hello world`, 190 }, 191 } 192 193 for _, test := range tests { 194 exp := ExperimentSpec{} 195 err := exp.UnmarshalJSON([]byte(test.specBytes)) 196 assert.Error(t, err) 197 assert.EqualError(t, err, test.errMessage) 198 } 199 } 200 201 func TestInitInsightsWithNumVersions(t *testing.T) { 202 r := ExperimentResult{ 203 Insights: &Insights{ 204 NumVersions: 1, 205 }, 206 } 207 208 err := r.initInsightsWithNumVersions(1) 209 assert.NoError(t, err) 210 211 // Mismatching version numbers 212 err = r.initInsightsWithNumVersions(2) 213 assert.Error(t, err) 214 }