github.com/jkawamoto/roadie-azure@v0.3.5/roadie/script_test.go (about) 1 // 2 // roadie/script_test.go 3 // 4 // Copyright (c) 2017 Junpei Kawamoto 5 // 6 // This file is part of Roadie Azure. 7 // 8 // Roadie Azure is free software: you can redistribute it and/or modify 9 // it under the terms of the GNU General Public License as published by 10 // the Free Software Foundation, either version 3 of the License, or 11 // (at your option) any later version. 12 // 13 // Roadie Azure is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License 19 // along with Roadie Azure. If not, see <http://www.gnu.org/licenses/>. 20 // 21 22 package roadie 23 24 import ( 25 "bytes" 26 "context" 27 "fmt" 28 "io/ioutil" 29 "log" 30 "os" 31 "os/exec" 32 "path/filepath" 33 "strings" 34 "testing" 35 36 "github.com/jkawamoto/roadie/cloud/azure" 37 "github.com/jkawamoto/roadie/cloud/azure/mock" 38 "github.com/jkawamoto/roadie/script" 39 ) 40 41 func TestPrepareSourceCode(t *testing.T) { 42 43 ctx := context.Background() 44 output := bytes.NewBuffer(nil) 45 s := Script{ 46 Script: new(script.Script), 47 Logger: log.New(output, "", log.LstdFlags), 48 } 49 50 t.Run("empty source", func(t *testing.T) { 51 output.Reset() 52 err := s.PrepareSourceCode(ctx) 53 if err != nil { 54 t.Fatalf("PrepareSourceCode returns an error: %v", err) 55 } 56 }) 57 58 t.Run("git source", func(t *testing.T) { 59 output.Reset() 60 61 temp, err := ioutil.TempDir("", "") 62 if err != nil { 63 t.Fatalf("cannot create a temporary directory: %v", err) 64 } 65 defer os.RemoveAll(temp) 66 wd, err := os.Getwd() 67 if err != nil { 68 t.Fatalf("cannot get the working directory: %v", err) 69 } 70 err = os.Chdir(temp) 71 if err != nil { 72 t.Fatalf("cannot change the current directory: %v", err) 73 } 74 defer os.Chdir(wd) 75 76 err = ioutil.WriteFile("test-file", []byte("aaa"), 0666) 77 if err != nil { 78 t.Errorf("cannot create a dummy file: %v", err) 79 } 80 81 s.Source = "https://github.com/jkawamoto/roadie-azure.git" 82 err = s.PrepareSourceCode(ctx) 83 if err != nil { 84 t.Fatalf("PrepareSourceCode returns an error: %v", err) 85 } 86 var matches []string 87 matches, err = filepath.Glob("roadie/*") 88 if err != nil { 89 t.Fatalf("Glob returns an error: %v", err) 90 } 91 for _, f := range matches { 92 _, err = os.Stat(filepath.Join(wd, filepath.Base(f))) 93 if err != nil { 94 t.Errorf("cloned file %q doesn't exist in %q", filepath.Base(f), wd) 95 } 96 } 97 if t.Failed() { 98 data, _ := exec.Command("ls", "-la").Output() 99 t.Log(string(data)) 100 } 101 }) 102 103 t.Run("dropbox source", func(t *testing.T) { 104 output.Reset() 105 106 temp, err := ioutil.TempDir("", "") 107 if err != nil { 108 t.Fatalf("cannot create a temporary directory: %v", err) 109 } 110 defer os.RemoveAll(temp) 111 wd, err := os.Getwd() 112 if err != nil { 113 t.Fatalf("cannot get the working directory: %v", err) 114 } 115 err = os.Chdir(temp) 116 if err != nil { 117 t.Fatalf("cannot change the current directory: %v", err) 118 } 119 defer os.Chdir(wd) 120 121 s.Source = "dropbox://sh/hlt9248hw1u54d6/AADLBa5TfbZKAacDzoARfFhqa" 122 err = s.PrepareSourceCode(ctx) 123 if err != nil { 124 t.Fatalf("PrepareSourceCode returns an error: %v", err) 125 } 126 _, err = os.Stat("aaa") 127 if err != nil { 128 t.Errorf("download source files don't have executable file %q", "aaa") 129 } 130 if t.Failed() { 131 data, _ := exec.Command("ls", "-la").Output() 132 t.Log(string(data)) 133 } 134 }) 135 136 t.Run("archived https source", func(t *testing.T) { 137 output.Reset() 138 139 temp, err := ioutil.TempDir("", "") 140 if err != nil { 141 t.Fatalf("cannot create a temporary directory: %v", err) 142 } 143 defer os.RemoveAll(temp) 144 wd, err := os.Getwd() 145 if err != nil { 146 t.Fatalf("cannot get the working directory: %v", err) 147 } 148 err = os.Chdir(temp) 149 if err != nil { 150 t.Fatalf("cannot change the current directory: %v", err) 151 } 152 defer os.Chdir(wd) 153 154 s.Source = "https://github.com/jkawamoto/roadie-azure/releases/download/v0.3.3/roadie-azure_linux_amd64.tar.gz" 155 err = s.PrepareSourceCode(ctx) 156 if err != nil { 157 t.Fatalf("PrepareSourceCode returns an error: %v", err) 158 } 159 _, err = os.Stat("roadie-azure_linux_amd64/roadie-azure") 160 if err != nil { 161 t.Errorf("download source files don't have executable file %q", "roadie-azure_linux_amd64/roadie-azure") 162 } 163 if t.Failed() { 164 data, _ := exec.Command("ls", "-la", "roadie-azure_linux_amd64").Output() 165 t.Log(string(data)) 166 } 167 }) 168 169 t.Run("plain https source", func(t *testing.T) { 170 output.Reset() 171 172 temp, err := ioutil.TempDir("", "") 173 if err != nil { 174 t.Fatalf("cannot create a temporary directory: %v", err) 175 } 176 defer os.RemoveAll(temp) 177 wd, err := os.Getwd() 178 if err != nil { 179 t.Fatalf("cannot get the working directory: %v", err) 180 } 181 err = os.Chdir(temp) 182 if err != nil { 183 t.Fatalf("cannot change the current directory: %v", err) 184 } 185 defer os.Chdir(wd) 186 187 s.Source = "https://raw.githubusercontent.com/jkawamoto/roadie-azure/master/README.md" 188 err = s.PrepareSourceCode(ctx) 189 if err != nil { 190 t.Fatalf("PrepareSourceCode returns an error: %v", err) 191 } 192 _, err = os.Stat("README.md") 193 if err != nil { 194 t.Errorf("download source files don't have executable file %q", "roadie") 195 } 196 if t.Failed() { 197 data, _ := exec.Command("ls", "-la").Output() 198 t.Log(string(data)) 199 } 200 }) 201 202 t.Run("archived file source", func(t *testing.T) { 203 output.Reset() 204 205 temp, err := ioutil.TempDir("", "") 206 if err != nil { 207 t.Fatalf("cannot create a temporary directory: %v", err) 208 } 209 defer os.RemoveAll(temp) 210 wd, err := os.Getwd() 211 if err != nil { 212 t.Fatalf("cannot get the working directory: %v", err) 213 } 214 err = os.Chdir(temp) 215 if err != nil { 216 t.Fatalf("cannot change the current directory: %v", err) 217 } 218 defer os.Chdir(wd) 219 220 s.Source = "file://" + filepath.Join(wd, "archive_test.zip") 221 err = s.PrepareSourceCode(ctx) 222 if err != nil { 223 t.Fatalf("PrepareSourceCode returns an error: %v", err) 224 } 225 _, err = os.Stat("abc.txt") 226 if err != nil { 227 t.Errorf("prepared source files don't have file %q", "abc.txt") 228 } 229 if t.Failed() { 230 data, _ := exec.Command("ls", "-la").Output() 231 t.Log(string(data)) 232 } 233 }) 234 235 t.Run("plain file source", func(t *testing.T) { 236 output.Reset() 237 238 temp, err := ioutil.TempDir("", "") 239 if err != nil { 240 t.Fatalf("cannot create a temporary directory: %v", err) 241 } 242 defer os.RemoveAll(temp) 243 wd, err := os.Getwd() 244 if err != nil { 245 t.Fatalf("cannot get the working directory: %v", err) 246 } 247 err = os.Chdir(temp) 248 if err != nil { 249 t.Fatalf("cannot change the current directory: %v", err) 250 } 251 defer os.Chdir(wd) 252 253 target := "script_test.go" 254 s.Source = "file://" + filepath.Join(wd, target) 255 err = s.PrepareSourceCode(ctx) 256 if err != nil { 257 t.Fatalf("PrepareSourceCode returns an error: %v", err) 258 } 259 _, err = os.Stat(target) 260 if err != nil { 261 t.Errorf("prepared source files don't have file %q", target) 262 } 263 if t.Failed() { 264 data, _ := exec.Command("ls", "-la").Output() 265 t.Log(string(data)) 266 } 267 }) 268 269 } 270 271 func TestDownloadDataFiles(t *testing.T) { 272 273 dir, err := ioutil.TempDir("", "") 274 if err != nil { 275 t.Fatalf("cannot create a temporary directory: %v", err) 276 } 277 defer os.RemoveAll(dir) 278 279 script := Script{ 280 Script: &script.Script{ 281 Data: []string{ 282 // Archived file from Dropbox with a destination. 283 fmt.Sprintf("dropbox://sh/hlt9248hw1u54d6/AADLBa5TfbZKAacDzoARfFhqa:%v/", dir), 284 // Archived file from Dropbox with renaming. 285 fmt.Sprintf("dropbox://sh/hlt9248hw1u54d6/AADLBa5TfbZKAacDzoARfFhqa:%v/dropbox.dat", dir), 286 // Archived file from a HTTP server with a destination. 287 fmt.Sprintf("https://github.com/jkawamoto/roadie-azure/releases/download/v0.3.3/roadie-azure_linux_amd64.tar.gz:%v/", dir), 288 // Archived file from a HTTP server with renaming. 289 fmt.Sprintf("https://github.com/jkawamoto/roadie-azure/releases/download/v0.3.3/roadie-azure_linux_amd64.tar.gz:%v/sample.dat", dir), 290 // Plain file from a HTTP server with a destination. 291 fmt.Sprintf("https://raw.githubusercontent.com/jkawamoto/roadie-azure/master/README.md:%v/", dir), 292 // Plain file from a HTTP server with renaming. 293 fmt.Sprintf("https://raw.githubusercontent.com/jkawamoto/roadie-azure/master/README.md:%v", filepath.Join(dir, "README2.md")), 294 }, 295 }, 296 Logger: log.New(ioutil.Discard, "", log.Lshortfile), 297 } 298 expectedFiles := []string{ 299 "aaa", 300 "dropbox.dat", 301 "roadie-azure_linux_amd64", 302 "sample.dat", 303 "README.md", 304 "README2.md", 305 } 306 307 err = script.DownloadDataFiles(context.Background()) 308 if err != nil { 309 t.Fatalf("DownloadDataFiles returns an error: %v", err) 310 } 311 for _, f := range expectedFiles { 312 _, err = os.Stat(filepath.Join(dir, f)) 313 if err != nil { 314 t.Errorf("downloaded file %q doesn't exist: %v", f, err) 315 } 316 } 317 318 } 319 320 func TestUploadResults(t *testing.T) { 321 322 var err error 323 tmp, err := ioutil.TempDir("", "") 324 if err != nil { 325 t.Fatalf("cannot create a temporary directory: %v", err) 326 } 327 defer os.RemoveAll(tmp) 328 329 script := Script{ 330 Script: &script.Script{ 331 Name: "task-abc", 332 Run: []string{ 333 "cmd1", 334 "cmd2", 335 }, 336 Upload: []string{ 337 filepath.Join(tmp, "*.txt"), 338 }, 339 }, 340 Logger: log.New(ioutil.Discard, "", log.LstdFlags), 341 } 342 var expected []string 343 344 // Create dummy output files. 345 for i := range script.Run { 346 filename := filepath.Join("/tmp", fmt.Sprintf("stdout%v.txt", i)) 347 _, err = os.Stat(filename) 348 if err != nil { 349 err = ioutil.WriteFile(filename, []byte(filename), 0644) 350 if err != nil { 351 t.Fatalf("cannot create dummy output file %v: %v", filename, err) 352 } 353 defer os.Remove(filename) 354 } 355 expected = append(expected, filepath.Base(filename)) 356 } 357 358 // Create dummy other outputs. 359 for i := 0; i != 10; i++ { 360 filename := filepath.Join(tmp, fmt.Sprintf("output-%v.txt", i)) 361 err = ioutil.WriteFile(filename, []byte(filename), 0644) 362 if err != nil { 363 t.Fatalf("cannot create dummy output file %v: %v", filename, err) 364 } 365 expected = append(expected, filepath.Base(filename)) 366 } 367 368 server := mock.NewStorageServer() 369 defer server.Close() 370 371 cli, err := server.GetClient() 372 if err != nil { 373 t.Fatalf("cannot get a client: %v", err) 374 } 375 376 store := azure.StorageService{ 377 Client: cli.GetBlobService(), 378 Logger: log.New(ioutil.Discard, "", log.LstdFlags), 379 } 380 381 err = script.UploadResults(context.Background(), &store) 382 if err != nil { 383 t.Fatalf("UploadResults returns an error: %v", err) 384 } 385 c, ok := server.Items["result"] 386 if !ok { 387 t.Fatalf("container %q doesn't exist", "result") 388 } 389 for _, f := range expected { 390 name := filepath.Join("abc", f) 391 _, ok = c[name] 392 if !ok { 393 t.Errorf("uploaded file %q doesn't exist", name) 394 } 395 } 396 if t.Failed() { 397 t.Log("following files are stored in the cloud storage") 398 for key, value := range c { 399 t.Logf("%v: %v", key, value) 400 } 401 } 402 403 } 404 405 func TestDockerfile(t *testing.T) { 406 407 script := Script{ 408 Script: &script.Script{ 409 APT: []string{ 410 "python-numpy", 411 "python-scipy", 412 }, 413 }, 414 } 415 416 buf, err := script.Dockerfile() 417 if err != nil { 418 t.Fatalf("cannot create a dockerfile: %v", err) 419 } 420 421 res := string(buf) 422 if !strings.Contains(res, "python-numpy") || !strings.Contains(res, "python-scipy") { 423 t.Error("Generated Dockerfile is not correct:", res) 424 } 425 426 } 427 428 func TestEntrypoint(t *testing.T) { 429 430 script := Script{ 431 Script: &script.Script{ 432 Run: []string{ 433 "cmd1", 434 "cmd2", 435 }, 436 }, 437 } 438 439 buf, err := script.Entrypoint() 440 if err != nil { 441 t.Fatalf("cannot create an entrypoint: %v", err) 442 } 443 444 res := string(buf) 445 if !strings.Contains(res, "cmd1") || !strings.Contains(res, "cmd2") { 446 t.Error("Generated entrypoint is not correct:", res) 447 } 448 if !strings.Contains(res, "stdout0.txt") || !strings.Contains(res, "stdout1.txt") { 449 t.Error("Generated entrypoint is not correct:", res) 450 } 451 452 }