1// Copyright 2015 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 blueprint
16
17import (
18	"reflect"
19	"testing"
20)
21
22var (
23	testModuleA = &moduleInfo{variantName: "testModuleA"}
24	testModuleB = &moduleInfo{variantName: "testModuleB"}
25	testModuleC = &moduleInfo{variantName: "testModuleC"}
26	testModuleD = &moduleInfo{variantName: "testModuleD"}
27	testModuleE = &moduleInfo{variantName: "testModuleE"}
28	testModuleF = &moduleInfo{variantName: "testModuleF"}
29)
30
31var spliceModulesTestCases = []struct {
32	in         []*moduleInfo
33	replace    *moduleInfo
34	with       []*moduleInfo
35	out        []*moduleInfo
36	reallocate bool
37}{
38	{
39		// Insert at the beginning
40		in:         []*moduleInfo{testModuleA, testModuleB, testModuleC},
41		replace:    testModuleA,
42		with:       []*moduleInfo{testModuleD, testModuleE},
43		out:        []*moduleInfo{testModuleD, testModuleE, testModuleB, testModuleC},
44		reallocate: true,
45	},
46	{
47		// Insert in the middle
48		in:         []*moduleInfo{testModuleA, testModuleB, testModuleC},
49		replace:    testModuleB,
50		with:       []*moduleInfo{testModuleD, testModuleE},
51		out:        []*moduleInfo{testModuleA, testModuleD, testModuleE, testModuleC},
52		reallocate: true,
53	},
54	{
55		// Insert at the end
56		in:         []*moduleInfo{testModuleA, testModuleB, testModuleC},
57		replace:    testModuleC,
58		with:       []*moduleInfo{testModuleD, testModuleE},
59		out:        []*moduleInfo{testModuleA, testModuleB, testModuleD, testModuleE},
60		reallocate: true,
61	},
62	{
63		// Insert over a single element
64		in:         []*moduleInfo{testModuleA},
65		replace:    testModuleA,
66		with:       []*moduleInfo{testModuleD, testModuleE},
67		out:        []*moduleInfo{testModuleD, testModuleE},
68		reallocate: true,
69	},
70	{
71		// Insert at the beginning without reallocating
72		in:         []*moduleInfo{testModuleA, testModuleB, testModuleC, nil}[0:3],
73		replace:    testModuleA,
74		with:       []*moduleInfo{testModuleD, testModuleE},
75		out:        []*moduleInfo{testModuleD, testModuleE, testModuleB, testModuleC},
76		reallocate: false,
77	},
78	{
79		// Insert in the middle without reallocating
80		in:         []*moduleInfo{testModuleA, testModuleB, testModuleC, nil}[0:3],
81		replace:    testModuleB,
82		with:       []*moduleInfo{testModuleD, testModuleE},
83		out:        []*moduleInfo{testModuleA, testModuleD, testModuleE, testModuleC},
84		reallocate: false,
85	},
86	{
87		// Insert at the end without reallocating
88		in:         []*moduleInfo{testModuleA, testModuleB, testModuleC, nil}[0:3],
89		replace:    testModuleC,
90		with:       []*moduleInfo{testModuleD, testModuleE},
91		out:        []*moduleInfo{testModuleA, testModuleB, testModuleD, testModuleE},
92		reallocate: false,
93	},
94	{
95		// Insert over a single element without reallocating
96		in:         []*moduleInfo{testModuleA, nil}[0:1],
97		replace:    testModuleA,
98		with:       []*moduleInfo{testModuleD, testModuleE},
99		out:        []*moduleInfo{testModuleD, testModuleE},
100		reallocate: false,
101	},
102}
103
104func TestSpliceModules(t *testing.T) {
105	for _, testCase := range spliceModulesTestCases {
106		in := make([]*moduleInfo, len(testCase.in), cap(testCase.in))
107		copy(in, testCase.in)
108		origIn := in
109		got := spliceModules(in, testCase.replace, testCase.with)
110		if !reflect.DeepEqual(got, testCase.out) {
111			t.Errorf("test case: %v, %v -> %v", testCase.in, testCase.replace, testCase.with)
112			t.Errorf("incorrect output:")
113			t.Errorf("  expected: %v", testCase.out)
114			t.Errorf("       got: %v", got)
115		}
116		if sameArray(origIn, got) != !testCase.reallocate {
117			t.Errorf("test case: %v, %v -> %v", testCase.in, testCase.replace, testCase.with)
118			not := ""
119			if !testCase.reallocate {
120				not = " not"
121			}
122			t.Errorf("  expected to%s reallocate", not)
123		}
124	}
125}
126
127func sameArray(a, b []*moduleInfo) bool {
128	return &a[0:cap(a)][cap(a)-1] == &b[0:cap(b)][cap(b)-1]
129}
130