github.com/cheshirekow/buildtools@v0.0.0-20200224190056-5d637702fe81/edit/buildozer_command_file_test.go (about)

     1  package edit
     2  
     3  import (
     4  	"reflect"
     5  	"strconv"
     6  	"strings"
     7  	"testing"
     8  )
     9  
    10  func TestEmptyCommandFileContainsNoCommands(t *testing.T) {
    11  	reader := strings.NewReader("")
    12  	commandsByBuildFile := make(map[string][]commandsForTarget)
    13  	appendCommandsFromReader(NewOpts(), reader, commandsByBuildFile)
    14  	t.Logf("Read commands:\n%s", prettyFormat(commandsByBuildFile))
    15  
    16  	if len(commandsByBuildFile) != 0 {
    17  		t.Error("No commands should be read")
    18  	}
    19  }
    20  
    21  func TestCommandFileWithOneSetAttributeLineContainsOneCommand(t *testing.T) {
    22  	commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget\n", t)
    23  	if len(commands) != 1 {
    24  		t.Error("Exactly one command should be read")
    25  		return
    26  	}
    27  	if commands[0].target != "//test-project:mytarget" {
    28  		t.Error("Read command should be for the correct target")
    29  	}
    30  	if !reflect.DeepEqual(commands[0].command, command{[]string{"set", "srcs", "mytarget.go"}}) {
    31  		t.Error("Read command should contain the correct command tokens")
    32  	}
    33  }
    34  
    35  func TestCommandFileWithTwoSetAttributesInOneLineContainsTwoCommands(t *testing.T) {
    36  	commands := parseCommandFile("set srcs mytarget.go|set deps //other-project:othertarget|//test-project:mytarget\n", t)
    37  	if len(commands) != 2 {
    38  		t.Error("Exactly two commands should be read")
    39  		return
    40  	}
    41  	if commands[0].target != "//test-project:mytarget" {
    42  		t.Error("First read command should be for the correct target")
    43  	}
    44  	if !reflect.DeepEqual(commands[0].command, command{[]string{"set", "srcs", "mytarget.go"}}) {
    45  		t.Error("First read command should contain the correct command tokens")
    46  	}
    47  	if commands[1].target != "//test-project:mytarget" {
    48  		t.Error("Second read command should be for the correct target")
    49  	}
    50  	if !reflect.DeepEqual(commands[1].command, command{[]string{"set", "deps", "//other-project:othertarget"}}) {
    51  		t.Error("Second read command should contain the correct command tokens")
    52  	}
    53  }
    54  
    55  func TestCommandFileWithTwoSetAttributesInSeparateLinesContainsTwoCommands(t *testing.T) {
    56  	commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget\nset deps //other-project:othertarget|//test-project:mytarget\n", t)
    57  	if len(commands) != 2 {
    58  		t.Error("Exactly two commands should be read")
    59  		return
    60  	}
    61  	if commands[0].target != "//test-project:mytarget" {
    62  		t.Error("First read command should be for the correct target")
    63  	}
    64  	if !reflect.DeepEqual(commands[0].command, command{[]string{"set", "srcs", "mytarget.go"}}) {
    65  		t.Error("First read command should contain the correct command tokens")
    66  	}
    67  	if commands[1].target != "//test-project:mytarget" {
    68  		t.Error("Second read command should be for the correct target")
    69  	}
    70  	if !reflect.DeepEqual(commands[1].command, command{[]string{"set", "deps", "//other-project:othertarget"}}) {
    71  		t.Error("Second read command should contain the correct command tokens")
    72  	}
    73  }
    74  
    75  func TestCommandFileWithoutTrailingNewlineContainsCommand(t *testing.T) {
    76  	commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget", t)
    77  	if len(commands) != 1 {
    78  		t.Error("Exactly one command should be read")
    79  		return
    80  	}
    81  	if commands[0].target != "//test-project:mytarget" {
    82  		t.Error("Read command should be for the correct target")
    83  	}
    84  }
    85  
    86  func TestBlankLinesInCommandFileAreIgnored(t *testing.T) {
    87  	commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget\n\n\n\n\nset srcs othertarget.go|//test-project:othertarget\n", t)
    88  	if len(commands) != 2 {
    89  		t.Error("Exactly two commands should be read")
    90  	}
    91  }
    92  
    93  func TestLongLineInCommandFileParsesAsOneCommand(t *testing.T) {
    94  	srcsLength := 10000
    95  
    96  	expectedCommandTokens := make([]string, srcsLength+2)
    97  	expectedCommandTokens[0] = "set"
    98  	expectedCommandTokens[1] = "srcs"
    99  	srcs := make([]string, srcsLength)
   100  	for i := 0; i < srcsLength; i++ {
   101  		src := "source_" + strconv.Itoa(i) + ".go"
   102  		srcs[i] = src
   103  		expectedCommandTokens[i+2] = src
   104  	}
   105  
   106  	commands := parseCommandFile("set srcs "+strings.Join(srcs, " ")+"|//test-project:mytarget\n", t)
   107  	if len(commands) != 1 {
   108  		t.Error("Exactly one command should be read")
   109  		return
   110  	}
   111  	if !reflect.DeepEqual(commands[0].command, command{expectedCommandTokens}) {
   112  		t.Errorf("First read command should contain the correct command tokens")
   113  	}
   114  }
   115  
   116  func parseCommandFile(fileContent string, t *testing.T) []parsedCommand {
   117  	reader := strings.NewReader(fileContent)
   118  	commandsByBuildFile := make(map[string][]commandsForTarget)
   119  	appendCommandsFromReader(NewOpts(), reader, commandsByBuildFile)
   120  	t.Logf("Read commands:\n%s", prettyFormat(commandsByBuildFile))
   121  	return extractCommands(commandsByBuildFile)
   122  }
   123  
   124  type parsedCommand struct {
   125  	command   command
   126  	target    string
   127  	buildFile string
   128  }
   129  
   130  func extractCommands(commandsByBuildFile map[string][]commandsForTarget) []parsedCommand {
   131  	out := make([]parsedCommand, 0)
   132  	for buildFile, targets := range commandsByBuildFile {
   133  		for _, target := range targets {
   134  			for _, command := range target.commands {
   135  				out = append(out, parsedCommand{command, target.target, buildFile})
   136  			}
   137  		}
   138  	}
   139  	return out
   140  }
   141  
   142  func prettyFormat(commandsByBuildFile map[string][]commandsForTarget) string {
   143  	out := ""
   144  	for buildFile, targets := range commandsByBuildFile {
   145  		out += buildFile + "\n"
   146  		for _, target := range targets {
   147  			out += "  target: " + target.target + "\n"
   148  			for _, command := range target.commands {
   149  				out += "    -"
   150  				for _, token := range command.tokens {
   151  					out += " " + token
   152  				}
   153  				out += "\n"
   154  			}
   155  		}
   156  	}
   157  	return out
   158  }