github.com/rainforestapp/rainforest-cli@v2.12.0+incompatible/rfml_test.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "os" 9 "path/filepath" 10 "reflect" 11 "sort" 12 "strconv" 13 "strings" 14 "testing" 15 16 "github.com/rainforestapp/rainforest-cli/rainforest" 17 "github.com/urfave/cli" 18 ) 19 20 func TestNewRFMLTest(t *testing.T) { 21 context := new(fakeContext) 22 testDefaultSpecFolder := "testing/" + defaultSpecFolder 23 24 /* 25 Declare reusable variables 26 */ 27 var contents []byte 28 var rfmlText string 29 var err error 30 var expectedRFMLPath string 31 var file *os.File 32 33 /* 34 Helper functions 35 */ 36 testExpectation := func(filePath string, title string) { 37 _, err = os.Stat(filePath) 38 if os.IsNotExist(err) { 39 t.Errorf("Expected RFML test does not exist: %v", filePath) 40 return 41 } 42 43 contents, err = ioutil.ReadFile(filePath) 44 if err != nil { 45 t.Error(err.Error()) 46 return 47 } 48 49 rfmlText = string(contents) 50 51 if !strings.Contains(rfmlText, title) { 52 t.Errorf("Expected title \"%v\" to appear in RFML test", title) 53 } 54 } 55 56 /* 57 No flags or args and spec folder doesn't exist 58 */ 59 context.mappings = map[string]interface{}{ 60 "test-folder": testDefaultSpecFolder, 61 } 62 63 err = newRFMLTest(context) 64 if err != nil { 65 t.Error(err.Error()) 66 } 67 68 expectedRFMLPath = filepath.Join(testDefaultSpecFolder, "Unnamed Test.rfml") 69 testExpectation(expectedRFMLPath, "Unnamed Test") 70 err = os.RemoveAll("./testing") 71 if err != nil { 72 t.Fatal(err.Error()) 73 } 74 75 /* 76 No flags or args and spec folder does exist 77 */ 78 err = os.MkdirAll(testDefaultSpecFolder, os.ModePerm) 79 if err != nil { 80 t.Fatal(err.Error()) 81 } 82 83 err = newRFMLTest(context) 84 if err != nil { 85 t.Error(err.Error()) 86 } 87 88 testExpectation(expectedRFMLPath, "Unnamed Test") 89 err = os.RemoveAll("./testing") 90 if err != nil { 91 t.Fatal(err.Error()) 92 } 93 94 /* 95 Test folder given 96 */ 97 specFolder := "./my_specs" 98 err = os.MkdirAll(specFolder, os.ModePerm) 99 if err != nil { 100 t.Fatal(err) 101 } 102 103 context.mappings = map[string]interface{}{ 104 "test-folder": specFolder, 105 } 106 107 err = newRFMLTest(context) 108 if err != nil { 109 err = os.RemoveAll(specFolder) 110 if err != nil { 111 t.Fatal(err.Error()) 112 } 113 t.Fatal(err) 114 } 115 116 expectedRFMLPath = filepath.Join(specFolder, "Unnamed Test.rfml") 117 testExpectation(expectedRFMLPath, "Unnamed Test") 118 err = os.RemoveAll(specFolder) 119 if err != nil { 120 t.Fatal(err.Error()) 121 } 122 123 /* 124 Filename argument given 125 */ 126 context.mappings = map[string]interface{}{ 127 "test-folder": testDefaultSpecFolder, 128 } 129 130 context.args = []string{"my_file_name.rfml"} 131 132 err = newRFMLTest(context) 133 if err != nil { 134 t.Fatal(err.Error()) 135 } 136 137 expectedRFMLPath = filepath.Join(testDefaultSpecFolder, "my_file_name.rfml") 138 testExpectation(expectedRFMLPath, "my_file_name") 139 err = os.RemoveAll("./testing") 140 if err != nil { 141 t.Fatal(err.Error()) 142 } 143 144 /* 145 Title argument given 146 */ 147 context.args = []string{"my_test_title"} 148 149 err = newRFMLTest(context) 150 if err != nil { 151 t.Fatal(err.Error()) 152 } 153 154 expectedRFMLPath = filepath.Join(testDefaultSpecFolder, "my_test_title.rfml") 155 testExpectation(expectedRFMLPath, "my_test_title") 156 err = os.RemoveAll("./testing") 157 if err != nil { 158 t.Fatal(err.Error()) 159 } 160 161 /* 162 Test folder flag is actually a file 163 */ 164 dummyFolder := "./dummy" 165 err = os.MkdirAll(dummyFolder, os.ModePerm) 166 if err != nil { 167 t.Fatal(err) 168 } 169 170 dummyFilePath := filepath.Join(dummyFolder, "dummy_file") 171 file, err = os.Create(dummyFilePath) 172 if err != nil { 173 err = os.RemoveAll(dummyFolder) 174 if err != nil { 175 t.Fatal(err.Error()) 176 } 177 t.Fatal(err) 178 } 179 180 file.Close() 181 182 context.args = []string{} 183 context.mappings = map[string]interface{}{ 184 "test-folder": dummyFilePath, 185 } 186 187 err = newRFMLTest(context) 188 if err == nil { 189 t.Error("Expecting an error, got nil") 190 } 191 192 os.RemoveAll(dummyFolder) 193 194 /* 195 RFML file already exists 196 */ 197 context.mappings = map[string]interface{}{ 198 "test-folder": testDefaultSpecFolder, 199 } 200 201 err = os.MkdirAll(testDefaultSpecFolder, os.ModePerm) 202 if err != nil { 203 t.Fatal(err.Error()) 204 } 205 206 existingRFMLPath := filepath.Join(testDefaultSpecFolder, "Unnamed Test.rfml") 207 file, err = os.Create(existingRFMLPath) 208 file.Close() 209 if err != nil { 210 t.Fatal(err.Error()) 211 } 212 213 err = newRFMLTest(context) 214 if err != nil { 215 err = os.RemoveAll("./testing") 216 if err != nil { 217 t.Fatal(err.Error()) 218 } 219 t.Fatal(err.Error()) 220 } 221 222 expectedRFMLPath = filepath.Join(testDefaultSpecFolder, "Unnamed Test (1).rfml") 223 _, err = os.Stat(expectedRFMLPath) 224 if err != nil { 225 t.Error(err.Error()) 226 } 227 228 err = os.RemoveAll("./testing") 229 if err != nil { 230 t.Fatal(err.Error()) 231 } 232 } 233 234 type testRfmlAPI struct { 235 testIDs []rainforest.TestIDPair 236 tests []rainforest.RFTest 237 handleUpdateTest func(*rainforest.RFTest) 238 } 239 240 func (t *testRfmlAPI) GetTestIDs() ([]rainforest.TestIDPair, error) { 241 return t.testIDs, nil 242 } 243 244 func (t *testRfmlAPI) GetTest(testID int) (*rainforest.RFTest, error) { 245 for _, test := range t.tests { 246 if test.TestID == testID { 247 return &test, nil 248 } 249 } 250 return nil, errors.New("Test ID not found") 251 } 252 253 func (t *testRfmlAPI) GetTests(*rainforest.RFTestFilters) ([]rainforest.RFTest, error) { 254 return t.tests, nil 255 } 256 257 func (t *testRfmlAPI) ClientToken() string { 258 return "abc123" 259 } 260 261 func (t *testRfmlAPI) CreateTest(_ *rainforest.RFTest) error { 262 // implement when needed 263 return errStub 264 } 265 266 func (t *testRfmlAPI) UpdateTest(test *rainforest.RFTest) error { 267 t.handleUpdateTest(test) 268 return nil 269 } 270 271 func (t *testRfmlAPI) ParseEmbeddedFiles(_ *rainforest.RFTest) error { 272 // implement when needed 273 return errStub 274 } 275 276 func createTestFolder(testFolderPath string) error { 277 absTestFolderPath, err := filepath.Abs(testFolderPath) 278 if err != nil { 279 return err 280 } 281 282 dirStat, err := os.Stat(absTestFolderPath) 283 if os.IsNotExist(err) { 284 os.MkdirAll(absTestFolderPath, os.ModePerm) 285 } else if err != nil { 286 return err 287 } else if !dirStat.IsDir() { 288 return fmt.Errorf("Test folder path is not a directory: %v", absTestFolderPath) 289 } 290 291 return nil 292 } 293 294 func cleanUpTestFolder(testFolderPath string) error { 295 _, err := os.Stat(testFolderPath) 296 297 if err != nil && os.IsNotExist(err) { 298 return err 299 } 300 301 err = os.RemoveAll(testFolderPath) 302 if err != nil { 303 return err 304 } 305 306 return nil 307 } 308 309 func TestUploadRFML(t *testing.T) { 310 context := new(fakeContext) 311 testAPI := new(testRfmlAPI) 312 testDefaultSpecFolder := "testing/" + defaultSpecFolder 313 314 defer func() { 315 err := cleanUpTestFolder("testing") 316 if err != nil { 317 t.Fatal(err.Error()) 318 } 319 }() 320 321 context.mappings = map[string]interface{}{ 322 "test-folder": testDefaultSpecFolder, 323 } 324 325 testID := 666 326 rfmlID := "unique_rfml_id" 327 title := "a very descriptive title" 328 var featureID rainforest.FeatureIDInt = 777 329 330 err := createTestFolder(testDefaultSpecFolder) 331 if err != nil { 332 t.Fatal(err.Error()) 333 } 334 335 testPath := filepath.Join(testDefaultSpecFolder, "valid_test.rfml") 336 337 testAPI.testIDs = []rainforest.TestIDPair{{ID: testID, RFMLID: rfmlID}} 338 339 // basic test 340 testAPI.handleUpdateTest = func(rfTest *rainforest.RFTest) { 341 testCases := []struct { 342 fieldName string 343 expected interface{} 344 got interface{} 345 }{ 346 {"test ID", testID, rfTest.TestID}, 347 {"RFML ID", rfmlID, rfTest.RFMLID}, 348 {"title", title, rfTest.Title}, 349 {"feature ID", featureID, rfTest.FeatureID}, 350 {"disabled state", "enabled", rfTest.State}, 351 } 352 353 for _, testCase := range testCases { 354 if testCase.got != testCase.expected { 355 t.Errorf("Incorrect value for %v. Expected %v, Got %v", testCase.fieldName, testCase.expected, testCase.got) 356 } 357 } 358 } 359 360 testContents := fmt.Sprintf(`#! %v 361 # title: %v 362 # feature_id: %v 363 `, rfmlID, title, featureID) 364 365 err = ioutil.WriteFile(testPath, []byte(testContents), os.ModePerm) 366 if err != nil { 367 t.Fatal(err.Error()) 368 } 369 370 err = uploadRFML(context, testAPI) 371 if err != nil { 372 t.Fatal(err.Error()) 373 } 374 375 // state is specified 376 testAPI.handleUpdateTest = func(rfTest *rainforest.RFTest) { 377 if rfTest.State != "disabled" { 378 t.Errorf("Incorrect value for state. Expected \"disabled\", Got %v", rfTest.State) 379 } 380 } 381 382 testContents = fmt.Sprintf(`#! %v 383 # title: %v 384 # state: disabled 385 `, rfmlID, title) 386 387 err = ioutil.WriteFile(testPath, []byte(testContents), os.ModePerm) 388 if err != nil { 389 t.Fatal(err.Error()) 390 } 391 392 err = uploadRFML(context, testAPI) 393 if err != nil { 394 t.Fatal(err.Error()) 395 } 396 } 397 398 func TestDeleteRFML(t *testing.T) { 399 // Test error in parsing file 400 dir, err := ioutil.TempDir("", "") 401 if err != nil { 402 t.Fatal(err.Error()) 403 } 404 defer os.RemoveAll(dir) 405 406 rfmlFilePath := filepath.Join(dir, "testing.rfml") 407 fileContents := `#! testing 408 # title: hello 409 # site_id: a_string 410 ` 411 err = ioutil.WriteFile(rfmlFilePath, []byte(fileContents), 0666) 412 if err != nil { 413 t.Fatal(err.Error()) 414 } 415 416 dummyMappings := map[string]interface{}{} 417 args := cli.Args{rfmlFilePath} 418 ctx := newFakeContext(dummyMappings, args) 419 420 err = deleteRFML(ctx) 421 if err == nil { 422 t.Fatal("Expected parse error but received no error.") 423 } 424 425 if _, ok := err.(*cli.ExitError); !ok { 426 t.Fatalf("Unexpected error type: %v", reflect.TypeOf(err)) 427 } 428 429 errMsg := err.Error() 430 if !strings.Contains(errMsg, rfmlFilePath) { 431 t.Errorf("Expected error to contain file path \"%v\". Got:\n%v", rfmlFilePath, errMsg) 432 } 433 } 434 435 func TestDownloadRFML(t *testing.T) { 436 context := new(fakeContext) 437 testAPI := new(testRfmlAPI) 438 testDefaultSpecFolder := "testing/" + defaultSpecFolder 439 440 defer func() { 441 err := cleanUpTestFolder("testing") 442 if err != nil { 443 t.Fatal(err.Error()) 444 } 445 }() 446 447 testID := 112233 448 rfmlID := "rfml_test_id" 449 title := "My Test Title" 450 featureID := 665544 451 452 rfTest := rainforest.RFTest{ 453 TestID: testID, 454 RFMLID: rfmlID, 455 Title: title, 456 FeatureID: rainforest.FeatureIDInt(featureID), 457 State: "enabled", 458 } 459 460 testAPI.testIDs = []rainforest.TestIDPair{{ID: testID, RFMLID: rfmlID}} 461 testAPI.tests = []rainforest.RFTest{rfTest} 462 463 paddedTestID := fmt.Sprintf("%010d", testID) 464 sanitizedTitle := "my_test_title" 465 expectedFileName := fmt.Sprintf("%v_%v.rfml", paddedTestID, sanitizedTitle) 466 expectedRFMLPath := filepath.Join(testDefaultSpecFolder, expectedFileName) 467 468 context.mappings = map[string]interface{}{ 469 "test-folder": testDefaultSpecFolder, 470 } 471 472 // basic test 473 err := downloadRFML(context, testAPI) 474 if err != nil { 475 t.Fatal(err.Error()) 476 } 477 478 fileInfo, err := os.Stat(expectedRFMLPath) 479 if os.IsNotExist(err) { 480 t.Fatalf("Expected RFML test does not exist: %v", expectedRFMLPath) 481 } 482 483 if fileInfo.Name() != expectedFileName { 484 t.Errorf("Expected RFML file path %v, got %v", expectedRFMLPath, fileInfo.Name()) 485 } else if err != nil { 486 t.Fatalf(err.Error()) 487 } 488 489 var contents []byte 490 contents, err = ioutil.ReadFile(expectedRFMLPath) 491 if err != nil { 492 t.Fatalf(err.Error()) 493 } 494 495 rfmlText := string(contents) 496 497 if !strings.Contains(rfmlText, title) { 498 t.Errorf("Expected title \"%v\" to appear in RFML test", title) 499 } 500 501 if !strings.Contains(rfmlText, rfmlID) { 502 t.Errorf("Expected RFML ID \"%v\" to appear in RFML test", rfmlID) 503 } 504 505 if !strings.Contains(rfmlText, strconv.Itoa(featureID)) { 506 t.Errorf("Expected Feature ID \"%v\" to appear in RFML test", featureID) 507 } 508 509 if strings.Contains(rfmlText, "state") { 510 t.Errorf("Did not expect state field in RFML test. Got %v", rfmlText) 511 } 512 513 // Test is disabled 514 rfTest.State = "disabled" 515 testAPI.tests = []rainforest.RFTest{rfTest} 516 517 err = downloadRFML(context, testAPI) 518 if err != nil { 519 t.Fatal(err.Error()) 520 } 521 522 fileInfo, err = os.Stat(expectedRFMLPath) 523 if os.IsNotExist(err) { 524 t.Fatalf("Expected RFML test does not exist: %v", expectedRFMLPath) 525 } 526 527 contents, err = ioutil.ReadFile(expectedRFMLPath) 528 if err != nil { 529 t.Fatalf(err.Error()) 530 } 531 rfmlText = string(contents) 532 533 if !strings.Contains(rfmlText, "# state: disabled") { 534 t.Errorf("Expected RFML test state to read disabled. Output: %v", rfmlText) 535 } 536 } 537 538 func TestSanitizeTestTitle(t *testing.T) { 539 // Test that it replaces non-alphanumeric characters with underscores 540 illegalTitle := `Foo\123|*&bar ` 541 sanitizedTitle := sanitizeTestTitle(illegalTitle) 542 expectedSanitizedTitle := "foo_123_bar" 543 544 if sanitizedTitle != expectedSanitizedTitle { 545 t.Errorf("Expected sanitized title to be %v, got %v", expectedSanitizedTitle, sanitizedTitle) 546 } 547 548 // Test that it truncates strings with more than 30 characters 549 longTitle := strings.Repeat("abc", 11) // 33 characters 550 sanitizedTitle = sanitizeTestTitle(longTitle) 551 expectedSanitizedTitle = strings.Repeat("abc", 10) // 30 characters 552 553 if sanitizedTitle != expectedSanitizedTitle { 554 t.Errorf("Expected sanitized title to be %v, got %v", expectedSanitizedTitle, sanitizedTitle) 555 } 556 } 557 558 func TestValidateEmbedded(t *testing.T) { 559 t1 := rainforest.RFTest{ 560 TestID: 1, 561 RFMLID: "1", 562 RFMLPath: "./1.rfml", 563 } 564 t2 := rainforest.RFTest{ 565 TestID: 2, 566 RFMLID: "2", 567 RFMLPath: "./2.rfml", 568 Steps: []interface{}{ 569 rainforest.RFEmbeddedTest{ 570 RFMLID: "1", 571 Redirect: true, 572 }, 573 }, 574 } 575 576 testAPI := new(testRfmlAPI) 577 testAPI.testIDs = []rainforest.TestIDPair{ 578 {ID: t1.TestID, RFMLID: t1.RFMLID}, 579 {ID: t2.TestID, RFMLID: t2.RFMLID}, 580 } 581 582 tests := []*rainforest.RFTest{&t2} 583 var err error 584 585 // With API access, the validation should be fine 586 err = validateRFMLFiles(tests, false, testAPI) 587 if err != nil { 588 t.Error("Non-local validation failed:", err) 589 } 590 591 // With local-only and all embedded tests available, the validation should 592 // be fine 593 allTests := append(tests, &t1) 594 err = validateRFMLFiles(allTests, true, testAPI) 595 if err != nil { 596 t.Error("Local-only validation with all tests failed:", err) 597 } 598 599 // With local-only and embedded tests not available locally, the validation 600 // should fail 601 err = validateRFMLFiles(tests, true, testAPI) 602 if err == nil { 603 t.Error("Local-only validation should have failed but didn't") 604 } else if err != errValidation { 605 t.Error("Unexpected error for local-only validation:", err) 606 } 607 } 608 609 func TestReadRFMLFiles(t *testing.T) { 610 dir := setupTestRFMLDir() 611 defer os.RemoveAll(dir) 612 613 var testCases = []struct { 614 files []string 615 wantFiles []string 616 wantError bool 617 }{ 618 { 619 files: []string{"a/a1.rfml"}, 620 wantFiles: []string{"a/a1.rfml"}, 621 }, 622 { 623 files: []string{"a"}, 624 wantFiles: []string{"a/a1.rfml", "a/a2.rfml", "a/a3.rfml"}, 625 }, 626 { 627 files: []string{"a", "a/a1.rfml", "b/b1.rfml"}, 628 wantFiles: []string{"a/a1.rfml", "a/a2.rfml", "a/a3.rfml", "b/b1.rfml"}, 629 }, 630 { 631 files: []string{""}, 632 wantFiles: []string{ 633 "a/a1.rfml", 634 "a/a2.rfml", 635 "a/a3.rfml", 636 "b/b1.rfml", 637 "b/a/b2.rfml", 638 "b/b/b3.rfml", 639 "b/b/b4.rfml", 640 "b/b/b5.rfml", 641 "standalone.rfml", 642 }, 643 }, 644 { 645 files: []string{"c"}, 646 wantError: true, 647 }, 648 { 649 // We want to just ignore bogus files, rather than error, so that 650 // shell expansions like foo/ab* still work 651 files: []string{"a/a1.rfml", "a/bogus.rf"}, 652 wantFiles: []string{"a/a1.rfml"}, 653 }, 654 } 655 656 for _, tc := range testCases { 657 fullFiles := []string{} 658 for _, f := range tc.files { 659 fullFiles = append(fullFiles, filepath.Join(dir, f)) 660 } 661 662 pTests, err := readRFMLFiles(fullFiles) 663 if err != nil && !tc.wantError { 664 t.Error(err) 665 continue 666 } else if err == nil && tc.wantError { 667 t.Errorf("Expected error when reading %v", tc.files) 668 continue 669 } 670 671 gotFiles := []string{} 672 for _, p := range pTests { 673 gotFiles = append(gotFiles, p.RFMLPath) 674 } 675 sort.Strings(gotFiles) 676 677 wantFiles := []string{} 678 for _, f := range tc.wantFiles { 679 wantFiles = append(wantFiles, filepath.Join(dir, f)) 680 } 681 sort.Strings(wantFiles) 682 683 if !reflect.DeepEqual(wantFiles, gotFiles) { 684 t.Errorf("Unexpected files returned (want: %v, got: %v)", wantFiles, gotFiles) 685 } 686 } 687 } 688 689 func TestReadRFMLFile(t *testing.T) { 690 // Test error in parsing file 691 dir, err := ioutil.TempDir("", "") 692 if err != nil { 693 t.Fatal(err.Error()) 694 } 695 defer os.RemoveAll(dir) 696 697 rfmlFilePath := filepath.Join(dir, "testing.rfml") 698 fileContents := `#! testing 699 # title: hello 700 # site_id: a_string 701 ` 702 err = ioutil.WriteFile(rfmlFilePath, []byte(fileContents), 0666) 703 if err != nil { 704 t.Fatal(err.Error()) 705 } 706 707 _, err = readRFMLFile(rfmlFilePath) 708 if err == nil { 709 t.Fatal("Expected parse error but received no error.") 710 } 711 712 errMsg := err.Error() 713 if !strings.Contains(errMsg, rfmlFilePath) { 714 t.Errorf("Expected error to contain file path \"%v\". Got:\n%v", rfmlFilePath, errMsg) 715 } 716 } 717 718 func setupTestRFMLDir() string { 719 var rfmlTests = []struct { 720 path string 721 content *rainforest.RFTest 722 }{ 723 { 724 path: "a/a1.rfml", 725 content: &rainforest.RFTest{ 726 RFMLID: "a1", 727 Tags: []string{"foo", "baz"}, 728 Execute: true, 729 Steps: []interface{}{ 730 rainforest.RFEmbeddedTest{ 731 RFMLID: "b4", 732 }, 733 }, 734 }, 735 }, 736 { 737 path: "a/a2.rfml", 738 content: &rainforest.RFTest{ 739 RFMLID: "a2", 740 Execute: true, 741 }, 742 }, 743 { 744 path: "a/a3.rfml", 745 content: &rainforest.RFTest{ 746 RFMLID: "a3", 747 Tags: []string{"bar"}, 748 Execute: true, 749 }, 750 }, 751 { 752 path: "b/b1.rfml", 753 content: &rainforest.RFTest{ 754 RFMLID: "b1", 755 Execute: true, 756 }, 757 }, 758 { 759 path: "b/a/b2.rfml", 760 content: &rainforest.RFTest{ 761 RFMLID: "b2", 762 Execute: true, 763 }, 764 }, 765 { 766 path: "b/b/b3.rfml", 767 content: &rainforest.RFTest{ 768 RFMLID: "b3", 769 Tags: []string{"foo"}, 770 Execute: false, 771 }, 772 }, 773 { 774 path: "b/b/b4.rfml", 775 content: &rainforest.RFTest{ 776 RFMLID: "b4", 777 Tags: []string{}, 778 Execute: true, 779 Steps: []interface{}{ 780 rainforest.RFEmbeddedTest{ 781 RFMLID: "b5", 782 }, 783 }, 784 }, 785 }, 786 { 787 path: "b/b/b5.rfml", 788 content: &rainforest.RFTest{ 789 RFMLID: "b5", 790 Execute: true, 791 }, 792 }, 793 { 794 path: "standalone.rfml", 795 content: &rainforest.RFTest{ 796 RFMLID: "standalone", 797 Execute: true, 798 }, 799 }, 800 { 801 path: "a/bogus.rf", 802 content: &rainforest.RFTest{ 803 RFMLID: "bogus", 804 Execute: true, 805 }, 806 }, 807 } 808 809 dir, err := ioutil.TempDir("", "") 810 if err != nil { 811 log.Fatal(err) 812 } 813 814 for _, subdir := range []string{"a", "b/a", "b/b"} { 815 err := os.MkdirAll(filepath.Join(dir, subdir), os.ModePerm) 816 if err != nil { 817 log.Fatal(err) 818 } 819 } 820 821 for i, test := range rfmlTests { 822 test.content.TestID = i 823 test.content.Title = test.content.RFMLID 824 p := filepath.Join(dir, test.path) 825 test.content.RFMLPath = p 826 f, err := os.Create(p) 827 if err != nil { 828 log.Fatal(err) 829 } 830 w := rainforest.NewRFMLWriter(f) 831 err = w.WriteRFMLTest(test.content) 832 if err != nil { 833 log.Fatal(err) 834 } 835 } 836 837 return dir 838 }