github.com/vlifesystems/rulehunter@v0.0.0-20180501090014-673078aa4a83/cmd/serve_test.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "path/filepath" 9 "reflect" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/phayes/freeport" 15 "github.com/vlifesystems/rulehunter/internal" 16 "github.com/vlifesystems/rulehunter/internal/testhelpers" 17 "github.com/vlifesystems/rulehunter/quitter" 18 ) 19 20 func TestRunServe(t *testing.T) { 21 wantEntries := []testhelpers.Entry{ 22 {Level: testhelpers.Error, 23 Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 5: did not find expected key"}, 24 {Level: testhelpers.Info, 25 Msg: "Processing experiment: debt.json, mode: train"}, 26 {Level: testhelpers.Info, 27 Msg: "Successfully processed experiment: debt.json, mode: train"}, 28 {Level: testhelpers.Info, 29 Msg: "Processing experiment: debt.yaml, mode: train"}, 30 {Level: testhelpers.Info, 31 Msg: "Successfully processed experiment: debt.yaml, mode: train"}, 32 {Level: testhelpers.Info, 33 Msg: "Processing experiment: debt2.json, mode: train"}, 34 {Level: testhelpers.Info, 35 Msg: "Successfully processed experiment: debt2.json, mode: train"}, 36 } 37 wantReportFiles := []string{ 38 // "debt2.json" 39 internal.MakeBuildFilename( 40 "train", 41 "", 42 "What is most likely to indicate success (2)", 43 ), 44 // "debt.yaml" 45 internal.MakeBuildFilename( 46 "train", 47 "testing", 48 "What is most likely to indicate success", 49 ), 50 // "debt.json" 51 internal.MakeBuildFilename( 52 "train", 53 "", 54 "What is most likely to indicate success", 55 ), 56 } 57 58 cfgDir := testhelpers.BuildConfigDirs(t, false) 59 cfgFilename := filepath.Join(cfgDir, "config.yaml") 60 defer os.RemoveAll(cfgDir) 61 testhelpers.MustWriteConfig(t, cfgDir, 100) 62 l := testhelpers.NewLogger() 63 q := quitter.New() 64 65 go func() { 66 if err := runServe(l, q, cfgFilename); err != nil { 67 t.Errorf("runServe: %s", err) 68 } 69 }() 70 71 if !testing.Short() { 72 time.Sleep(2 * time.Second) 73 } 74 75 experimentFiles := []string{ 76 "debt.json", 77 "debt.yaml", 78 "0debt_broken.yaml", 79 "debt2.json", 80 "debt.jso", 81 } 82 for _, f := range experimentFiles { 83 testhelpers.CopyFile( 84 t, 85 filepath.Join("fixtures", f), 86 filepath.Join(cfgDir, "experiments"), 87 ) 88 } 89 90 hasQuit := false 91 tickerC := time.NewTicker(100 * time.Millisecond).C 92 timeoutC := time.NewTimer(20 * time.Second).C 93 for !hasQuit { 94 select { 95 case <-tickerC: 96 gotReportFiles := testhelpers.GetFilesInDir( 97 t, 98 filepath.Join(cfgDir, "build", "reports"), 99 ) 100 if len(gotReportFiles) == 3 { 101 q.Quit() 102 hasQuit = true 103 break 104 } 105 case <-timeoutC: 106 t.Fatal("runServe hasn't stopped") 107 } 108 } 109 110 time.Sleep(4 * time.Second) 111 112 gotReportFiles := testhelpers.GetFilesInDir( 113 t, 114 filepath.Join(cfgDir, "build", "reports"), 115 ) 116 if !reflect.DeepEqual(gotReportFiles, wantReportFiles) { 117 t.Errorf("GetFilesInDir - got: %v\n want: %v", 118 gotReportFiles, wantReportFiles) 119 } 120 121 gotEntries := l.GetEntries() 122 if err := doLogEntriesMatch(gotEntries, wantEntries); err != nil { 123 t.Errorf("GetEntries: %s", err) 124 } 125 // TODO: Test all files generated 126 } 127 128 func TestRunServe_http(t *testing.T) { 129 httpPort, err := freeport.GetFreePort() 130 if err != nil { 131 t.Fatalf("GetFreePort: %d", err) 132 } 133 wantEntries := []testhelpers.Entry{ 134 {Level: testhelpers.Info, 135 Msg: fmt.Sprintf("Starting http server on port: %d", httpPort)}, 136 {Level: testhelpers.Info, 137 Msg: fmt.Sprintf("Shutdown http server on port: %d", httpPort)}, 138 {Level: testhelpers.Error, 139 Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 5: did not find expected key"}, 140 {Level: testhelpers.Info, 141 Msg: "Processing experiment: debt.json, mode: train"}, 142 {Level: testhelpers.Info, 143 Msg: "Successfully processed experiment: debt.json, mode: train"}, 144 {Level: testhelpers.Info, 145 Msg: "Processing experiment: debt.yaml, mode: train"}, 146 {Level: testhelpers.Info, 147 Msg: "Successfully processed experiment: debt.yaml, mode: train"}, 148 {Level: testhelpers.Info, 149 Msg: "Processing experiment: debt2.json, mode: train"}, 150 {Level: testhelpers.Info, 151 Msg: "Successfully processed experiment: debt2.json, mode: train"}, 152 } 153 154 cfgDir := testhelpers.BuildConfigDirs(t, false) 155 cfgFilename := filepath.Join(cfgDir, "config.yaml") 156 defer os.RemoveAll(cfgDir) 157 testhelpers.MustWriteConfig(t, cfgDir, 100, httpPort) 158 l := testhelpers.NewLogger() 159 q := quitter.New() 160 161 go func() { 162 if err := runServe(l, q, cfgFilename); err != nil { 163 t.Errorf("runServe: %s", err) 164 } 165 }() 166 167 if !testing.Short() { 168 time.Sleep(2 * time.Second) 169 } 170 171 experimentFiles := []string{ 172 "debt.json", 173 "debt.yaml", 174 "0debt_broken.yaml", 175 "debt2.json", 176 "debt.jso", 177 } 178 for _, f := range experimentFiles { 179 testhelpers.CopyFile( 180 t, 181 filepath.Join("fixtures", f), 182 filepath.Join(cfgDir, "experiments"), 183 ) 184 } 185 186 wantText := "Rulehunter" 187 resp, err := http.Get(fmt.Sprintf("http://localhost:%d", httpPort)) 188 if err != nil { 189 q.Quit() 190 t.Fatalf("http.Get: %s", err) 191 } 192 if resp.StatusCode != 200 { 193 q.Quit() 194 t.Fatalf("received non-200 response: %d", resp.StatusCode) 195 } 196 body, err := ioutil.ReadAll(resp.Body) 197 if err != nil { 198 q.Quit() 199 t.Fatal(err) 200 } 201 if !strings.Contains(string(body[:]), wantText) { 202 t.Errorf("web page doesn't contain: %s", wantText) 203 } 204 205 hasQuit := false 206 tickerC := time.NewTicker(100 * time.Millisecond).C 207 timeoutC := time.NewTimer(20 * time.Second).C 208 for !hasQuit { 209 select { 210 case <-tickerC: 211 gotReportFiles := testhelpers.GetFilesInDir( 212 t, 213 filepath.Join(cfgDir, "build", "reports"), 214 ) 215 if len(gotReportFiles) == 3 { 216 q.Quit() 217 hasQuit = true 218 break 219 } 220 case <-timeoutC: 221 q.Quit() 222 t.Fatal("runServe hasn't stopped") 223 } 224 } 225 226 time.Sleep(4 * time.Second) 227 228 gotEntries := l.GetEntries() 229 if err := doLogEntriesMatch(gotEntries, wantEntries); err != nil { 230 t.Errorf("GetEntries: %s", err) 231 } 232 // TODO: Test all files generated 233 }