1// Copyright 2014 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package parser 16 17import ( 18 "bytes" 19 "testing" 20) 21 22var validPrinterTestCases = []struct { 23 name string 24 input string 25 output string 26}{ 27 { 28 input: ` 29foo {} 30`, 31 output: ` 32foo {} 33`, 34 }, 35 { 36 input: ` 37foo(name= "abc",num= 4,) 38`, 39 output: ` 40foo { 41 name: "abc", 42 num: 4, 43} 44`, 45 }, 46 { 47 input: ` 48 foo { 49 stuff: ["asdf", "jkl;", "qwert", 50 "uiop", "bnm,"] 51 } 52 `, 53 output: ` 54foo { 55 stuff: [ 56 "asdf", 57 "bnm,", 58 "jkl;", 59 "qwert", 60 "uiop", 61 ], 62} 63`, 64 }, 65 { 66 input: ` 67 var = "asdf" 68 foo { 69 stuff: ["asdf"] + var, 70 }`, 71 output: ` 72var = "asdf" 73foo { 74 stuff: ["asdf"] + var, 75} 76`, 77 }, 78 { 79 input: ` 80 var = "asdf" 81 foo { 82 stuff: [ 83 "asdf" 84 ] + var, 85 }`, 86 output: ` 87var = "asdf" 88foo { 89 stuff: [ 90 "asdf", 91 ] + var, 92} 93`, 94 }, 95 { 96 input: ` 97 var = "asdf" 98 foo { 99 stuff: ["asdf"] + var + ["qwert"], 100 }`, 101 output: ` 102var = "asdf" 103foo { 104 stuff: ["asdf"] + var + ["qwert"], 105} 106`, 107 }, 108 { 109 input: ` 110 foo { 111 stuff: { 112 isGood: true, 113 name: "bar", 114 num: 4, 115 } 116 } 117 `, 118 output: ` 119foo { 120 stuff: { 121 isGood: true, 122 name: "bar", 123 num: 4, 124 }, 125} 126`, 127 }, 128 { 129 input: ` 130// comment1 131foo { 132 // comment2 133 isGood: true, // comment3 134} 135`, 136 output: ` 137// comment1 138foo { 139 // comment2 140 isGood: true, // comment3 141} 142`, 143 }, 144 { 145 input: ` 146foo { 147 name: "abc", 148 num: 4, 149} 150 151bar { 152 name: "def", 153 num: 5, 154} 155 `, 156 output: ` 157foo { 158 name: "abc", 159 num: 4, 160} 161 162bar { 163 name: "def", 164 num: 5, 165} 166`, 167 }, 168 { 169 input: ` 170foo { 171 bar: "b" + 172 "a" + 173 "z", 174} 175`, 176 output: ` 177foo { 178 bar: "b" + 179 "a" + 180 "z", 181} 182`, 183 }, 184 { 185 input: ` 186foo = "stuff" 187bar = foo 188baz = foo + bar 189baz += foo 190`, 191 output: ` 192foo = "stuff" 193bar = foo 194baz = foo + bar 195baz += foo 196`, 197 }, 198 { 199 input: ` 200foo = 100 201bar = foo 202baz = foo + bar 203baz += foo 204`, 205 output: ` 206foo = 100 207bar = foo 208baz = foo + bar 209baz += foo 210`, 211 }, 212 { 213 input: ` 214foo = "bar " + 215 "" + 216 "baz" 217`, 218 output: ` 219foo = "bar " + 220 "" + 221 "baz" 222`, 223 }, 224 { 225 input: ` 226//test 227test /* test */ { 228 srcs: [ 229 /*"bootstrap/bootstrap.go", 230 "bootstrap/cleanup.go",*/ 231 "bootstrap/command.go", 232 "bootstrap/doc.go", //doc.go 233 "bootstrap/config.go", //config.go 234 ], 235 deps: ["libabc"], 236 incs: [] 237} //test 238//test 239test2 { 240} 241 242 243//test3 244`, 245 output: ` 246//test 247test /* test */ { 248 srcs: [ 249 /*"bootstrap/bootstrap.go", 250 "bootstrap/cleanup.go",*/ 251 "bootstrap/command.go", 252 "bootstrap/config.go", //config.go 253 "bootstrap/doc.go", //doc.go 254 ], 255 deps: ["libabc"], 256 incs: [], 257} //test 258//test 259 260test2 { 261} 262 263//test3 264`, 265 }, 266 { 267 input: ` 268// test 269module // test 270 271 { 272 srcs 273 : [ 274 "src1.c", 275 "src2.c", 276 ], 277//test 278} 279//test2 280`, 281 output: ` 282// test 283module { // test 284 srcs: [ 285 "src1.c", 286 "src2.c", 287 ], 288 //test 289} 290 291//test2 292`, 293 }, 294 { 295 input: ` 296/*test { 297 test: true, 298}*/ 299 300test { 301/*test: true,*/ 302} 303 304// This 305/* Is *//* A */ // A 306// A 307 308// Multiline 309// Comment 310 311test {} 312 313// This 314/* Is */ 315// A 316// Trailing 317 318// Multiline 319// Comment 320`, 321 output: ` 322/*test { 323 test: true, 324}*/ 325 326test { 327 /*test: true,*/ 328} 329 330// This 331/* Is */ /* A */ // A 332// A 333 334// Multiline 335// Comment 336 337test {} 338 339// This 340/* Is */ 341// A 342// Trailing 343 344// Multiline 345// Comment 346`, 347 }, 348 { 349 input: ` 350test // test 351 352// test 353{ 354} 355`, 356 output: ` 357test { // test 358// test 359} 360`, 361 }, 362 { 363 input: ` 364// test 365stuff { 366 namespace: "google", 367 string_vars: [ 368 { 369 var: "one", 370 values: [ "one_a", "one_b",], 371 }, 372 { 373 var: "two", 374 values: [ "two_a", "two_b", ], 375 }, 376 ], 377}`, 378 output: ` 379// test 380stuff { 381 namespace: "google", 382 string_vars: [ 383 { 384 var: "one", 385 values: [ 386 "one_a", 387 "one_b", 388 ], 389 }, 390 { 391 var: "two", 392 values: [ 393 "two_a", 394 "two_b", 395 ], 396 }, 397 ], 398} 399`, 400 }, 401 { 402 input: ` 403// test 404stuff { 405 namespace: "google", 406 list_of_lists: [ 407 [ "a", "b" ], 408 [ "c", "d" ], 409 ], 410} 411`, 412 output: ` 413// test 414stuff { 415 namespace: "google", 416 list_of_lists: [ 417 [ 418 "a", 419 "b", 420 ], 421 [ 422 "c", 423 "d", 424 ], 425 ], 426} 427`, 428 }, 429 { 430 input: ` 431// test 432stuff { 433 namespace: "google", 434 list_of_structs: [{ key1: "a", key2: "b" }], 435} 436`, 437 output: ` 438// test 439stuff { 440 namespace: "google", 441 list_of_structs: [ 442 { 443 key1: "a", 444 key2: "b", 445 }, 446 ], 447} 448`, 449 }, 450 { 451 input: ` 452// test 453foo { 454 stuff: [ 455 "a", // great comment 456 "b", 457 ], 458} 459`, 460 output: ` 461// test 462foo { 463 stuff: [ 464 "a", // great comment 465 "b", 466 ], 467} 468`, 469 }, 470 { 471 input: ` 472// test 473foo { 474 stuff: [ 475 "a", 476 // b comment 477 "b", 478 ], 479} 480`, 481 output: ` 482// test 483foo { 484 stuff: [ 485 "a", 486 // b comment 487 "b", 488 ], 489} 490`, 491 }, 492 { 493 input: ` 494// test 495foo { 496 stuff: [ 497 "a", // a comment 498 // b comment 499 "b", 500 ], 501} 502`, 503 output: ` 504// test 505foo { 506 stuff: [ 507 "a", // a comment 508 // b comment 509 "b", 510 ], 511} 512`, 513 }, 514 { 515 input: ` 516// test 517foo { 518 stuff: [ 519 "a", 520 // b comment 521 // on multiline 522 "b", 523 ], 524} 525`, 526 output: ` 527// test 528foo { 529 stuff: [ 530 "a", 531 // b comment 532 // on multiline 533 "b", 534 ], 535} 536`, 537 }, 538 { // Line comment are treat as groups separator 539 input: ` 540// test 541foo { 542 stuff: [ 543 "b", 544 // a comment 545 "a", 546 ], 547} 548`, 549 output: ` 550// test 551foo { 552 stuff: [ 553 "b", 554 // a comment 555 "a", 556 ], 557} 558`, 559 }, 560 { 561 name: "Basic selects", 562 input: ` 563// test 564foo { 565 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 566 "a": "a2", 567 // test2 568 "b": "b2", 569 // test3 570 default: "c2", 571 }), 572} 573`, 574 output: ` 575// test 576foo { 577 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 578 "a": "a2", 579 // test2 580 "b": "b2", 581 // test3 582 default: "c2", 583 }), 584} 585`, 586 }, 587 { 588 name: "Remove select with only default", 589 input: ` 590// test 591foo { 592 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 593 // test2 594 default: "c2", 595 }), 596} 597`, 598 output: ` 599// test 600foo { 601 stuff: "c2", // test2 602} 603`, 604 }, 605 { 606 name: "Appended selects", 607 input: ` 608// test 609foo { 610 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 611 "a": "a2", 612 // test2 613 "b": "b2", 614 // test3 615 default: "c2", 616 }) + select(release_variable("RELEASE_TEST"), { 617 "d": "d2", 618 "e": "e2", 619 default: "f2", 620 }), 621} 622`, 623 output: ` 624// test 625foo { 626 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 627 "a": "a2", 628 // test2 629 "b": "b2", 630 // test3 631 default: "c2", 632 }) + select(release_variable("RELEASE_TEST"), { 633 "d": "d2", 634 "e": "e2", 635 default: "f2", 636 }), 637} 638`, 639 }, 640 { 641 name: "Select with unset property", 642 input: ` 643foo { 644 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 645 "foo": unset, 646 default: "c2", 647 }), 648} 649`, 650 output: ` 651foo { 652 stuff: select(soong_config_variable("my_namespace", "my_variable"), { 653 "foo": unset, 654 default: "c2", 655 }), 656} 657`, 658 }, 659 { 660 name: "Multi-condition select", 661 input: ` 662foo { 663 stuff: select((arch(), os()), { 664 ("x86", "linux"): "a", 665 (default, default): "b", 666 }), 667} 668`, 669 output: ` 670foo { 671 stuff: select((arch(), os()), { 672 ("x86", "linux"): "a", 673 (default, default): "b", 674 }), 675} 676`, 677 }, 678 { 679 name: "Multi-condition select with conditions on new lines", 680 input: ` 681foo { 682 stuff: select((arch(), 683 os()), { 684 ("x86", "linux"): "a", 685 (default, default): "b", 686 }), 687} 688`, 689 output: ` 690foo { 691 stuff: select(( 692 arch(), 693 os(), 694 ), { 695 ("x86", "linux"): "a", 696 (default, default): "b", 697 }), 698} 699`, 700 }, 701 { 702 name: "Select with multiline inner expression", 703 input: ` 704foo { 705 cflags: [ 706 "-DPRODUCT_COMPATIBLE_PROPERTY", 707 "-DRIL_SHLIB", 708 "-Wall", 709 "-Wextra", 710 "-Werror", 711 ] + select(soong_config_variable("sim", "sim_count"), { 712 "2": [ 713 "-DANDROID_MULTI_SIM", 714 "-DANDROID_SIM_COUNT_2", 715 ], 716 default: [], 717 }), 718} 719`, 720 output: ` 721foo { 722 cflags: [ 723 "-DPRODUCT_COMPATIBLE_PROPERTY", 724 "-DRIL_SHLIB", 725 "-Wall", 726 "-Werror", 727 "-Wextra", 728 ] + select(soong_config_variable("sim", "sim_count"), { 729 "2": [ 730 "-DANDROID_MULTI_SIM", 731 "-DANDROID_SIM_COUNT_2", 732 ], 733 default: [], 734 }), 735} 736`, 737 }, 738} 739 740func TestPrinter(t *testing.T) { 741 for _, testCase := range validPrinterTestCases { 742 t.Run(testCase.name, func(t *testing.T) { 743 in := testCase.input[1:] 744 expected := testCase.output[1:] 745 746 r := bytes.NewBufferString(in) 747 file, errs := Parse("", r, NewScope(nil)) 748 if len(errs) != 0 { 749 t.Errorf("test case: %s", in) 750 t.Errorf("unexpected errors:") 751 for _, err := range errs { 752 t.Errorf(" %s", err) 753 } 754 t.FailNow() 755 } 756 757 SortLists(file) 758 759 got, err := Print(file) 760 if err != nil { 761 t.Errorf("test case: %s", in) 762 t.Errorf("unexpected error: %s", err) 763 t.FailNow() 764 } 765 766 if string(got) != expected { 767 t.Errorf("test case: %s", in) 768 t.Errorf(" expected: %s", expected) 769 t.Errorf(" got: %s", string(got)) 770 } 771 }) 772 } 773} 774