github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/command/helpers_test.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "net/http" 8 "os" 9 "reflect" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/hashicorp/nomad/api" 15 "github.com/hashicorp/nomad/helper" 16 "github.com/hashicorp/nomad/helper/flatmap" 17 "github.com/kr/pretty" 18 "github.com/mitchellh/cli" 19 ) 20 21 func TestHelpers_FormatKV(t *testing.T) { 22 t.Parallel() 23 in := []string{"alpha|beta", "charlie|delta", "echo|"} 24 out := formatKV(in) 25 26 expect := "alpha = beta\n" 27 expect += "charlie = delta\n" 28 expect += "echo = <none>" 29 30 if out != expect { 31 t.Fatalf("expect: %s, got: %s", expect, out) 32 } 33 } 34 35 func TestHelpers_FormatList(t *testing.T) { 36 t.Parallel() 37 in := []string{"alpha|beta||delta"} 38 out := formatList(in) 39 40 expect := "alpha beta <none> delta" 41 42 if out != expect { 43 t.Fatalf("expect: %s, got: %s", expect, out) 44 } 45 } 46 47 func TestHelpers_NodeID(t *testing.T) { 48 t.Parallel() 49 srv, _, _ := testServer(t, false, nil) 50 defer srv.Shutdown() 51 52 meta := Meta{Ui: new(cli.MockUi)} 53 client, err := meta.Client() 54 if err != nil { 55 t.FailNow() 56 } 57 58 // This is because there is no client 59 if _, err := getLocalNodeID(client); err == nil { 60 t.Fatalf("getLocalNodeID() should fail") 61 } 62 } 63 64 func TestHelpers_LineLimitReader_NoTimeLimit(t *testing.T) { 65 t.Parallel() 66 helloString := `hello 67 world 68 this 69 is 70 a 71 test` 72 73 noLines := "jskdfhjasdhfjkajkldsfdlsjkahfkjdsafa" 74 75 cases := []struct { 76 Input string 77 Output string 78 Lines int 79 SearchLimit int 80 }{ 81 { 82 Input: helloString, 83 Output: helloString, 84 Lines: 6, 85 SearchLimit: 1000, 86 }, 87 { 88 Input: helloString, 89 Output: `world 90 this 91 is 92 a 93 test`, 94 Lines: 5, 95 SearchLimit: 1000, 96 }, 97 { 98 Input: helloString, 99 Output: `test`, 100 Lines: 1, 101 SearchLimit: 1000, 102 }, 103 { 104 Input: helloString, 105 Output: "", 106 Lines: 0, 107 SearchLimit: 1000, 108 }, 109 { 110 Input: helloString, 111 Output: helloString, 112 Lines: 6, 113 SearchLimit: 1, // Exceed the limit 114 }, 115 { 116 Input: noLines, 117 Output: noLines, 118 Lines: 10, 119 SearchLimit: 1000, 120 }, 121 { 122 Input: noLines, 123 Output: noLines, 124 Lines: 10, 125 SearchLimit: 2, 126 }, 127 } 128 129 for i, c := range cases { 130 in := ioutil.NopCloser(strings.NewReader(c.Input)) 131 limit := NewLineLimitReader(in, c.Lines, c.SearchLimit, 0) 132 outBytes, err := ioutil.ReadAll(limit) 133 if err != nil { 134 t.Fatalf("case %d failed: %v", i, err) 135 } 136 137 out := string(outBytes) 138 if out != c.Output { 139 t.Fatalf("case %d: got %q; want %q", i, out, c.Output) 140 } 141 } 142 } 143 144 type testReadCloser struct { 145 data chan []byte 146 } 147 148 func (t *testReadCloser) Read(p []byte) (n int, err error) { 149 select { 150 case b, ok := <-t.data: 151 if !ok { 152 return 0, io.EOF 153 } 154 155 return copy(p, b), nil 156 case <-time.After(10 * time.Millisecond): 157 return 0, nil 158 } 159 } 160 161 func (t *testReadCloser) Close() error { 162 close(t.data) 163 return nil 164 } 165 166 func TestHelpers_LineLimitReader_TimeLimit(t *testing.T) { 167 t.Parallel() 168 // Create the test reader 169 in := &testReadCloser{data: make(chan []byte)} 170 171 // Set up the reader such that it won't hit the line/buffer limit and could 172 // only terminate if it hits the time limit 173 limit := NewLineLimitReader(in, 1000, 1000, 100*time.Millisecond) 174 175 expected := []byte("hello world") 176 177 resultCh := make(chan struct{}) 178 go func() { 179 outBytes, err := ioutil.ReadAll(limit) 180 if err != nil { 181 t.Fatalf("ReadAll failed: %v", err) 182 } 183 184 if reflect.DeepEqual(outBytes, expected) { 185 close(resultCh) 186 return 187 } 188 }() 189 190 // Send the data 191 in.data <- expected 192 in.Close() 193 194 select { 195 case <-resultCh: 196 case <-time.After(1 * time.Second): 197 t.Fatalf("did not exit by time limit") 198 } 199 } 200 201 const ( 202 job = `job "job1" { 203 type = "service" 204 datacenters = [ "dc1" ] 205 group "group1" { 206 count = 1 207 task "task1" { 208 driver = "exec" 209 resources = {} 210 } 211 restart{ 212 attempts = 10 213 mode = "delay" 214 interval = "15s" 215 } 216 } 217 }` 218 ) 219 220 var ( 221 expectedApiJob = &api.Job{ 222 ID: helper.StringToPtr("job1"), 223 Name: helper.StringToPtr("job1"), 224 Type: helper.StringToPtr("service"), 225 Datacenters: []string{"dc1"}, 226 TaskGroups: []*api.TaskGroup{ 227 { 228 Name: helper.StringToPtr("group1"), 229 Count: helper.IntToPtr(1), 230 RestartPolicy: &api.RestartPolicy{ 231 Attempts: helper.IntToPtr(10), 232 Interval: helper.TimeToPtr(15 * time.Second), 233 Mode: helper.StringToPtr("delay"), 234 }, 235 236 Tasks: []*api.Task{ 237 { 238 Driver: "exec", 239 Name: "task1", 240 Resources: &api.Resources{}, 241 }, 242 }, 243 }, 244 }, 245 } 246 ) 247 248 // Test APIJob with local jobfile 249 func TestJobGetter_LocalFile(t *testing.T) { 250 t.Parallel() 251 fh, err := ioutil.TempFile("", "nomad") 252 if err != nil { 253 t.Fatalf("err: %s", err) 254 } 255 defer os.Remove(fh.Name()) 256 _, err = fh.WriteString(job) 257 if err != nil { 258 t.Fatalf("err: %s", err) 259 } 260 261 j := &JobGetter{} 262 aj, err := j.ApiJob(fh.Name()) 263 if err != nil { 264 t.Fatalf("err: %s", err) 265 } 266 267 if !reflect.DeepEqual(expectedApiJob, aj) { 268 eflat := flatmap.Flatten(expectedApiJob, nil, false) 269 aflat := flatmap.Flatten(aj, nil, false) 270 t.Fatalf("got:\n%v\nwant:\n%v", aflat, eflat) 271 } 272 } 273 274 // Test StructJob with jobfile from HTTP Server 275 func TestJobGetter_HTTPServer(t *testing.T) { 276 t.Parallel() 277 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 278 fmt.Fprintf(w, job) 279 }) 280 go http.ListenAndServe("127.0.0.1:12345", nil) 281 282 // Wait until HTTP Server starts certainly 283 time.Sleep(100 * time.Millisecond) 284 285 j := &JobGetter{} 286 aj, err := j.ApiJob("http://127.0.0.1:12345/") 287 if err != nil { 288 t.Fatalf("err: %s", err) 289 } 290 if !reflect.DeepEqual(expectedApiJob, aj) { 291 for _, d := range pretty.Diff(expectedApiJob, aj) { 292 t.Logf(d) 293 } 294 t.Fatalf("Unexpected file") 295 } 296 }