xref: /aosp_15_r20/build/soong/rust/project_json_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage rust
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"encoding/json"
19*333d2b36SAndroid Build Coastguard Worker	"io/ioutil"
20*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
21*333d2b36SAndroid Build Coastguard Worker	"sort"
22*333d2b36SAndroid Build Coastguard Worker	"strings"
23*333d2b36SAndroid Build Coastguard Worker	"testing"
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/android"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Worker// testProjectJson run the generation of rust-project.json. It returns the raw
29*333d2b36SAndroid Build Coastguard Worker// content of the generated file.
30*333d2b36SAndroid Build Coastguard Workerfunc testProjectJson(t *testing.T, bp string) []byte {
31*333d2b36SAndroid Build Coastguard Worker	result := android.GroupFixturePreparers(
32*333d2b36SAndroid Build Coastguard Worker		prepareForRustTest,
33*333d2b36SAndroid Build Coastguard Worker		android.FixtureMergeEnv(map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}),
34*333d2b36SAndroid Build Coastguard Worker	).RunTestWithBp(t, bp)
35*333d2b36SAndroid Build Coastguard Worker
36*333d2b36SAndroid Build Coastguard Worker	// The JSON file is generated via WriteFileToOutputDir. Therefore, it
37*333d2b36SAndroid Build Coastguard Worker	// won't appear in the Output of the TestingSingleton. Manually verify
38*333d2b36SAndroid Build Coastguard Worker	// it exists.
39*333d2b36SAndroid Build Coastguard Worker	content, err := ioutil.ReadFile(filepath.Join(result.Config.SoongOutDir(), rustProjectJsonFileName))
40*333d2b36SAndroid Build Coastguard Worker	if err != nil {
41*333d2b36SAndroid Build Coastguard Worker		t.Errorf("rust-project.json has not been generated")
42*333d2b36SAndroid Build Coastguard Worker	}
43*333d2b36SAndroid Build Coastguard Worker	return content
44*333d2b36SAndroid Build Coastguard Worker}
45*333d2b36SAndroid Build Coastguard Worker
46*333d2b36SAndroid Build Coastguard Worker// validateJsonCrates validates that content follows the basic structure of
47*333d2b36SAndroid Build Coastguard Worker// rust-project.json. It returns the crates attribute if the validation
48*333d2b36SAndroid Build Coastguard Worker// succeeded.
49*333d2b36SAndroid Build Coastguard Worker// It uses an empty interface instead of relying on a defined structure to
50*333d2b36SAndroid Build Coastguard Worker// avoid a strong dependency on our implementation.
51*333d2b36SAndroid Build Coastguard Workerfunc validateJsonCrates(t *testing.T, rawContent []byte) []interface{} {
52*333d2b36SAndroid Build Coastguard Worker	var content interface{}
53*333d2b36SAndroid Build Coastguard Worker	err := json.Unmarshal(rawContent, &content)
54*333d2b36SAndroid Build Coastguard Worker	if err != nil {
55*333d2b36SAndroid Build Coastguard Worker		t.Errorf("Unable to parse the rust-project.json as JSON: %v", err)
56*333d2b36SAndroid Build Coastguard Worker	}
57*333d2b36SAndroid Build Coastguard Worker	root, ok := content.(map[string]interface{})
58*333d2b36SAndroid Build Coastguard Worker	if !ok {
59*333d2b36SAndroid Build Coastguard Worker		t.Errorf("Unexpected JSON format: %v", content)
60*333d2b36SAndroid Build Coastguard Worker	}
61*333d2b36SAndroid Build Coastguard Worker	if _, ok = root["crates"]; !ok {
62*333d2b36SAndroid Build Coastguard Worker		t.Errorf("No crates attribute in rust-project.json: %v", root)
63*333d2b36SAndroid Build Coastguard Worker	}
64*333d2b36SAndroid Build Coastguard Worker	crates, ok := root["crates"].([]interface{})
65*333d2b36SAndroid Build Coastguard Worker	if !ok {
66*333d2b36SAndroid Build Coastguard Worker		t.Errorf("Unexpected crates format: %v", root["crates"])
67*333d2b36SAndroid Build Coastguard Worker	}
68*333d2b36SAndroid Build Coastguard Worker	return crates
69*333d2b36SAndroid Build Coastguard Worker}
70*333d2b36SAndroid Build Coastguard Worker
71*333d2b36SAndroid Build Coastguard Worker// validateCrate ensures that a crate can be parsed as a map.
72*333d2b36SAndroid Build Coastguard Workerfunc validateCrate(t *testing.T, crate interface{}) map[string]interface{} {
73*333d2b36SAndroid Build Coastguard Worker	c, ok := crate.(map[string]interface{})
74*333d2b36SAndroid Build Coastguard Worker	if !ok {
75*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("Unexpected type for crate: %v", c)
76*333d2b36SAndroid Build Coastguard Worker	}
77*333d2b36SAndroid Build Coastguard Worker	return c
78*333d2b36SAndroid Build Coastguard Worker}
79*333d2b36SAndroid Build Coastguard Worker
80*333d2b36SAndroid Build Coastguard Worker// validateDependencies parses the dependencies for a crate. It returns a list
81*333d2b36SAndroid Build Coastguard Worker// of the dependencies name.
82*333d2b36SAndroid Build Coastguard Workerfunc validateDependencies(t *testing.T, crate map[string]interface{}) []string {
83*333d2b36SAndroid Build Coastguard Worker	var dependencies []string
84*333d2b36SAndroid Build Coastguard Worker	deps, ok := crate["deps"].([]interface{})
85*333d2b36SAndroid Build Coastguard Worker	if !ok {
86*333d2b36SAndroid Build Coastguard Worker		t.Errorf("Unexpected format for deps: %v", crate["deps"])
87*333d2b36SAndroid Build Coastguard Worker	}
88*333d2b36SAndroid Build Coastguard Worker	for _, dep := range deps {
89*333d2b36SAndroid Build Coastguard Worker		d, ok := dep.(map[string]interface{})
90*333d2b36SAndroid Build Coastguard Worker		if !ok {
91*333d2b36SAndroid Build Coastguard Worker			t.Errorf("Unexpected format for dependency: %v", dep)
92*333d2b36SAndroid Build Coastguard Worker		}
93*333d2b36SAndroid Build Coastguard Worker		name, ok := d["name"].(string)
94*333d2b36SAndroid Build Coastguard Worker		if !ok {
95*333d2b36SAndroid Build Coastguard Worker			t.Errorf("Dependency is missing the name key: %v", d)
96*333d2b36SAndroid Build Coastguard Worker		}
97*333d2b36SAndroid Build Coastguard Worker		dependencies = append(dependencies, name)
98*333d2b36SAndroid Build Coastguard Worker	}
99*333d2b36SAndroid Build Coastguard Worker	return dependencies
100*333d2b36SAndroid Build Coastguard Worker}
101*333d2b36SAndroid Build Coastguard Worker
102*333d2b36SAndroid Build Coastguard Workerfunc TestProjectJsonDep(t *testing.T) {
103*333d2b36SAndroid Build Coastguard Worker	bp := `
104*333d2b36SAndroid Build Coastguard Worker	rust_library {
105*333d2b36SAndroid Build Coastguard Worker		name: "liba",
106*333d2b36SAndroid Build Coastguard Worker		srcs: ["a/src/lib.rs"],
107*333d2b36SAndroid Build Coastguard Worker		crate_name: "a"
108*333d2b36SAndroid Build Coastguard Worker	}
109*333d2b36SAndroid Build Coastguard Worker	rust_library {
110*333d2b36SAndroid Build Coastguard Worker		name: "libb",
111*333d2b36SAndroid Build Coastguard Worker		srcs: ["b/src/lib.rs"],
112*333d2b36SAndroid Build Coastguard Worker		crate_name: "b",
113*333d2b36SAndroid Build Coastguard Worker		rlibs: ["liba"],
114*333d2b36SAndroid Build Coastguard Worker	}
115*333d2b36SAndroid Build Coastguard Worker	`
116*333d2b36SAndroid Build Coastguard Worker	jsonContent := testProjectJson(t, bp)
117*333d2b36SAndroid Build Coastguard Worker	validateJsonCrates(t, jsonContent)
118*333d2b36SAndroid Build Coastguard Worker}
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Workerfunc TestProjectJsonProcMacroDep(t *testing.T) {
121*333d2b36SAndroid Build Coastguard Worker	bp := `
122*333d2b36SAndroid Build Coastguard Worker	rust_proc_macro {
123*333d2b36SAndroid Build Coastguard Worker		name: "libproc_macro",
124*333d2b36SAndroid Build Coastguard Worker		srcs: ["a/src/lib.rs"],
125*333d2b36SAndroid Build Coastguard Worker		crate_name: "proc_macro"
126*333d2b36SAndroid Build Coastguard Worker	}
127*333d2b36SAndroid Build Coastguard Worker	rust_library {
128*333d2b36SAndroid Build Coastguard Worker		name: "librust",
129*333d2b36SAndroid Build Coastguard Worker		srcs: ["b/src/lib.rs"],
130*333d2b36SAndroid Build Coastguard Worker		crate_name: "rust",
131*333d2b36SAndroid Build Coastguard Worker		proc_macros: ["libproc_macro"],
132*333d2b36SAndroid Build Coastguard Worker	}
133*333d2b36SAndroid Build Coastguard Worker	`
134*333d2b36SAndroid Build Coastguard Worker	jsonContent := testProjectJson(t, bp)
135*333d2b36SAndroid Build Coastguard Worker	crates := validateJsonCrates(t, jsonContent)
136*333d2b36SAndroid Build Coastguard Worker	libproc_macro_count := 0
137*333d2b36SAndroid Build Coastguard Worker	librust_count := 0
138*333d2b36SAndroid Build Coastguard Worker	for _, c := range crates {
139*333d2b36SAndroid Build Coastguard Worker		crate := validateCrate(t, c)
140*333d2b36SAndroid Build Coastguard Worker		procMacro, ok := crate["is_proc_macro"].(bool)
141*333d2b36SAndroid Build Coastguard Worker		if !ok {
142*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Unexpected type for is_proc_macro: %v", crate["is_proc_macro"])
143*333d2b36SAndroid Build Coastguard Worker		}
144*333d2b36SAndroid Build Coastguard Worker
145*333d2b36SAndroid Build Coastguard Worker		name, ok := crate["display_name"].(string)
146*333d2b36SAndroid Build Coastguard Worker		if !ok {
147*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Unexpected type for display_name: %v", crate["display_name"])
148*333d2b36SAndroid Build Coastguard Worker		}
149*333d2b36SAndroid Build Coastguard Worker
150*333d2b36SAndroid Build Coastguard Worker		switch name {
151*333d2b36SAndroid Build Coastguard Worker		case "libproc_macro":
152*333d2b36SAndroid Build Coastguard Worker			libproc_macro_count += 1
153*333d2b36SAndroid Build Coastguard Worker			if !procMacro {
154*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("'libproc_macro' is marked with is_proc_macro=false")
155*333d2b36SAndroid Build Coastguard Worker			}
156*333d2b36SAndroid Build Coastguard Worker		case "librust":
157*333d2b36SAndroid Build Coastguard Worker			librust_count += 1
158*333d2b36SAndroid Build Coastguard Worker			if procMacro {
159*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("'librust' is not a proc macro crate, but is marked with is_proc_macro=true")
160*333d2b36SAndroid Build Coastguard Worker			}
161*333d2b36SAndroid Build Coastguard Worker		default:
162*333d2b36SAndroid Build Coastguard Worker			break
163*333d2b36SAndroid Build Coastguard Worker		}
164*333d2b36SAndroid Build Coastguard Worker	}
165*333d2b36SAndroid Build Coastguard Worker
166*333d2b36SAndroid Build Coastguard Worker	if libproc_macro_count != 1 || librust_count != 1 {
167*333d2b36SAndroid Build Coastguard Worker		t.Fatalf("Unexpected crate counts: libproc_macro_count: %v, librust_count: %v",
168*333d2b36SAndroid Build Coastguard Worker			libproc_macro_count, librust_count)
169*333d2b36SAndroid Build Coastguard Worker	}
170*333d2b36SAndroid Build Coastguard Worker}
171*333d2b36SAndroid Build Coastguard Worker
172*333d2b36SAndroid Build Coastguard Workerfunc TestProjectJsonFeature(t *testing.T) {
173*333d2b36SAndroid Build Coastguard Worker	bp := `
174*333d2b36SAndroid Build Coastguard Worker	rust_library {
175*333d2b36SAndroid Build Coastguard Worker		name: "liba",
176*333d2b36SAndroid Build Coastguard Worker		srcs: ["a/src/lib.rs"],
177*333d2b36SAndroid Build Coastguard Worker		crate_name: "a",
178*333d2b36SAndroid Build Coastguard Worker		features: ["f1", "f2"]
179*333d2b36SAndroid Build Coastguard Worker	}
180*333d2b36SAndroid Build Coastguard Worker	`
181*333d2b36SAndroid Build Coastguard Worker	jsonContent := testProjectJson(t, bp)
182*333d2b36SAndroid Build Coastguard Worker	crates := validateJsonCrates(t, jsonContent)
183*333d2b36SAndroid Build Coastguard Worker	for _, c := range crates {
184*333d2b36SAndroid Build Coastguard Worker		crate := validateCrate(t, c)
185*333d2b36SAndroid Build Coastguard Worker		cfgs, ok := crate["cfg"].([]interface{})
186*333d2b36SAndroid Build Coastguard Worker		if !ok {
187*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Unexpected type for cfgs: %v", crate)
188*333d2b36SAndroid Build Coastguard Worker		}
189*333d2b36SAndroid Build Coastguard Worker		expectedCfgs := []string{"feature=\"f1\"", "feature=\"f2\""}
190*333d2b36SAndroid Build Coastguard Worker		foundCfgs := []string{}
191*333d2b36SAndroid Build Coastguard Worker		for _, cfg := range cfgs {
192*333d2b36SAndroid Build Coastguard Worker			cfg, ok := cfg.(string)
193*333d2b36SAndroid Build Coastguard Worker			if !ok {
194*333d2b36SAndroid Build Coastguard Worker				t.Fatalf("Unexpected type for cfg: %v", cfg)
195*333d2b36SAndroid Build Coastguard Worker			}
196*333d2b36SAndroid Build Coastguard Worker			foundCfgs = append(foundCfgs, cfg)
197*333d2b36SAndroid Build Coastguard Worker		}
198*333d2b36SAndroid Build Coastguard Worker		sort.Strings(foundCfgs)
199*333d2b36SAndroid Build Coastguard Worker		for i, foundCfg := range foundCfgs {
200*333d2b36SAndroid Build Coastguard Worker			if foundCfg != expectedCfgs[i] {
201*333d2b36SAndroid Build Coastguard Worker				t.Errorf("Incorrect features: got %v; want %v", foundCfg, expectedCfgs[i])
202*333d2b36SAndroid Build Coastguard Worker			}
203*333d2b36SAndroid Build Coastguard Worker		}
204*333d2b36SAndroid Build Coastguard Worker	}
205*333d2b36SAndroid Build Coastguard Worker}
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Workerfunc TestProjectJsonBinary(t *testing.T) {
208*333d2b36SAndroid Build Coastguard Worker	bp := `
209*333d2b36SAndroid Build Coastguard Worker	rust_binary {
210*333d2b36SAndroid Build Coastguard Worker		name: "libz",
211*333d2b36SAndroid Build Coastguard Worker		srcs: ["z/src/lib.rs"],
212*333d2b36SAndroid Build Coastguard Worker		crate_name: "z"
213*333d2b36SAndroid Build Coastguard Worker	}
214*333d2b36SAndroid Build Coastguard Worker	`
215*333d2b36SAndroid Build Coastguard Worker	jsonContent := testProjectJson(t, bp)
216*333d2b36SAndroid Build Coastguard Worker	crates := validateJsonCrates(t, jsonContent)
217*333d2b36SAndroid Build Coastguard Worker	for _, c := range crates {
218*333d2b36SAndroid Build Coastguard Worker		crate := validateCrate(t, c)
219*333d2b36SAndroid Build Coastguard Worker		rootModule, ok := crate["root_module"].(string)
220*333d2b36SAndroid Build Coastguard Worker		if !ok {
221*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
222*333d2b36SAndroid Build Coastguard Worker		}
223*333d2b36SAndroid Build Coastguard Worker		if rootModule == "z/src/lib.rs" {
224*333d2b36SAndroid Build Coastguard Worker			return
225*333d2b36SAndroid Build Coastguard Worker		}
226*333d2b36SAndroid Build Coastguard Worker	}
227*333d2b36SAndroid Build Coastguard Worker	t.Errorf("Entry for binary %q not found: %s", "a", jsonContent)
228*333d2b36SAndroid Build Coastguard Worker}
229*333d2b36SAndroid Build Coastguard Worker
230*333d2b36SAndroid Build Coastguard Workerfunc TestProjectJsonBindGen(t *testing.T) {
231*333d2b36SAndroid Build Coastguard Worker	buildOS := android.TestConfig(t.TempDir(), nil, "", nil).BuildOS
232*333d2b36SAndroid Build Coastguard Worker
233*333d2b36SAndroid Build Coastguard Worker	bp := `
234*333d2b36SAndroid Build Coastguard Worker	rust_library {
235*333d2b36SAndroid Build Coastguard Worker		name: "libd",
236*333d2b36SAndroid Build Coastguard Worker		srcs: ["d/src/lib.rs"],
237*333d2b36SAndroid Build Coastguard Worker		rlibs: ["libbindings1"],
238*333d2b36SAndroid Build Coastguard Worker		crate_name: "d"
239*333d2b36SAndroid Build Coastguard Worker	}
240*333d2b36SAndroid Build Coastguard Worker	rust_bindgen {
241*333d2b36SAndroid Build Coastguard Worker		name: "libbindings1",
242*333d2b36SAndroid Build Coastguard Worker		crate_name: "bindings1",
243*333d2b36SAndroid Build Coastguard Worker		source_stem: "bindings1",
244*333d2b36SAndroid Build Coastguard Worker		host_supported: true,
245*333d2b36SAndroid Build Coastguard Worker		wrapper_src: "src/any.h",
246*333d2b36SAndroid Build Coastguard Worker	}
247*333d2b36SAndroid Build Coastguard Worker	rust_library_host {
248*333d2b36SAndroid Build Coastguard Worker		name: "libe",
249*333d2b36SAndroid Build Coastguard Worker		srcs: ["e/src/lib.rs"],
250*333d2b36SAndroid Build Coastguard Worker		rustlibs: ["libbindings2"],
251*333d2b36SAndroid Build Coastguard Worker		crate_name: "e"
252*333d2b36SAndroid Build Coastguard Worker	}
253*333d2b36SAndroid Build Coastguard Worker	rust_bindgen_host {
254*333d2b36SAndroid Build Coastguard Worker		name: "libbindings2",
255*333d2b36SAndroid Build Coastguard Worker		crate_name: "bindings2",
256*333d2b36SAndroid Build Coastguard Worker		source_stem: "bindings2",
257*333d2b36SAndroid Build Coastguard Worker		wrapper_src: "src/any.h",
258*333d2b36SAndroid Build Coastguard Worker	}
259*333d2b36SAndroid Build Coastguard Worker	`
260*333d2b36SAndroid Build Coastguard Worker	jsonContent := testProjectJson(t, bp)
261*333d2b36SAndroid Build Coastguard Worker	crates := validateJsonCrates(t, jsonContent)
262*333d2b36SAndroid Build Coastguard Worker	for _, c := range crates {
263*333d2b36SAndroid Build Coastguard Worker		crate := validateCrate(t, c)
264*333d2b36SAndroid Build Coastguard Worker		rootModule, ok := crate["root_module"].(string)
265*333d2b36SAndroid Build Coastguard Worker		if !ok {
266*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
267*333d2b36SAndroid Build Coastguard Worker		}
268*333d2b36SAndroid Build Coastguard Worker		if strings.Contains(rootModule, "libbindings1") && !strings.Contains(rootModule, "android_arm64") {
269*333d2b36SAndroid Build Coastguard Worker			t.Errorf("The source path for libbindings1 does not contain android_arm64, got %v", rootModule)
270*333d2b36SAndroid Build Coastguard Worker		}
271*333d2b36SAndroid Build Coastguard Worker		if strings.Contains(rootModule, "libbindings2") && !strings.Contains(rootModule, buildOS.String()) {
272*333d2b36SAndroid Build Coastguard Worker			t.Errorf("The source path for libbindings2 does not contain the BuildOs, got %v; want %v",
273*333d2b36SAndroid Build Coastguard Worker				rootModule, buildOS.String())
274*333d2b36SAndroid Build Coastguard Worker		}
275*333d2b36SAndroid Build Coastguard Worker		// Check that libbindings1 does not depend on itself.
276*333d2b36SAndroid Build Coastguard Worker		if strings.Contains(rootModule, "libbindings1") {
277*333d2b36SAndroid Build Coastguard Worker			for _, depName := range validateDependencies(t, crate) {
278*333d2b36SAndroid Build Coastguard Worker				if depName == "bindings1" {
279*333d2b36SAndroid Build Coastguard Worker					t.Errorf("libbindings1 depends on itself")
280*333d2b36SAndroid Build Coastguard Worker				}
281*333d2b36SAndroid Build Coastguard Worker			}
282*333d2b36SAndroid Build Coastguard Worker		}
283*333d2b36SAndroid Build Coastguard Worker		if strings.Contains(rootModule, "d/src/lib.rs") {
284*333d2b36SAndroid Build Coastguard Worker			// Check that libd depends on libbindings1
285*333d2b36SAndroid Build Coastguard Worker			found := false
286*333d2b36SAndroid Build Coastguard Worker			for _, depName := range validateDependencies(t, crate) {
287*333d2b36SAndroid Build Coastguard Worker				if depName == "bindings1" {
288*333d2b36SAndroid Build Coastguard Worker					found = true
289*333d2b36SAndroid Build Coastguard Worker					break
290*333d2b36SAndroid Build Coastguard Worker				}
291*333d2b36SAndroid Build Coastguard Worker			}
292*333d2b36SAndroid Build Coastguard Worker			if !found {
293*333d2b36SAndroid Build Coastguard Worker				t.Errorf("libd does not depend on libbindings1: %v", crate)
294*333d2b36SAndroid Build Coastguard Worker			}
295*333d2b36SAndroid Build Coastguard Worker			// Check that OUT_DIR is populated.
296*333d2b36SAndroid Build Coastguard Worker			env, ok := crate["env"].(map[string]interface{})
297*333d2b36SAndroid Build Coastguard Worker			if !ok {
298*333d2b36SAndroid Build Coastguard Worker				t.Errorf("libd does not have its environment variables set: %v", crate)
299*333d2b36SAndroid Build Coastguard Worker			}
300*333d2b36SAndroid Build Coastguard Worker			if _, ok = env["OUT_DIR"]; !ok {
301*333d2b36SAndroid Build Coastguard Worker				t.Errorf("libd does not have its OUT_DIR set: %v", env)
302*333d2b36SAndroid Build Coastguard Worker			}
303*333d2b36SAndroid Build Coastguard Worker
304*333d2b36SAndroid Build Coastguard Worker		}
305*333d2b36SAndroid Build Coastguard Worker	}
306*333d2b36SAndroid Build Coastguard Worker}
307*333d2b36SAndroid Build Coastguard Worker
308*333d2b36SAndroid Build Coastguard Workerfunc TestProjectJsonMultiVersion(t *testing.T) {
309*333d2b36SAndroid Build Coastguard Worker	bp := `
310*333d2b36SAndroid Build Coastguard Worker	rust_library {
311*333d2b36SAndroid Build Coastguard Worker		name: "liba1",
312*333d2b36SAndroid Build Coastguard Worker		srcs: ["a1/src/lib.rs"],
313*333d2b36SAndroid Build Coastguard Worker		crate_name: "a"
314*333d2b36SAndroid Build Coastguard Worker	}
315*333d2b36SAndroid Build Coastguard Worker	rust_library {
316*333d2b36SAndroid Build Coastguard Worker		name: "liba2",
317*333d2b36SAndroid Build Coastguard Worker		srcs: ["a2/src/lib.rs"],
318*333d2b36SAndroid Build Coastguard Worker		crate_name: "a",
319*333d2b36SAndroid Build Coastguard Worker	}
320*333d2b36SAndroid Build Coastguard Worker	rust_library {
321*333d2b36SAndroid Build Coastguard Worker		name: "libb",
322*333d2b36SAndroid Build Coastguard Worker		srcs: ["b/src/lib.rs"],
323*333d2b36SAndroid Build Coastguard Worker		crate_name: "b",
324*333d2b36SAndroid Build Coastguard Worker		rustlibs: ["liba1", "liba2"],
325*333d2b36SAndroid Build Coastguard Worker	}
326*333d2b36SAndroid Build Coastguard Worker	`
327*333d2b36SAndroid Build Coastguard Worker	jsonContent := testProjectJson(t, bp)
328*333d2b36SAndroid Build Coastguard Worker	crates := validateJsonCrates(t, jsonContent)
329*333d2b36SAndroid Build Coastguard Worker	for _, c := range crates {
330*333d2b36SAndroid Build Coastguard Worker		crate := validateCrate(t, c)
331*333d2b36SAndroid Build Coastguard Worker		rootModule, ok := crate["root_module"].(string)
332*333d2b36SAndroid Build Coastguard Worker		if !ok {
333*333d2b36SAndroid Build Coastguard Worker			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
334*333d2b36SAndroid Build Coastguard Worker		}
335*333d2b36SAndroid Build Coastguard Worker		// Make sure that b has 2 different dependencies.
336*333d2b36SAndroid Build Coastguard Worker		if rootModule == "b/src/lib.rs" {
337*333d2b36SAndroid Build Coastguard Worker			aCount := 0
338*333d2b36SAndroid Build Coastguard Worker			deps := validateDependencies(t, crate)
339*333d2b36SAndroid Build Coastguard Worker			for _, depName := range deps {
340*333d2b36SAndroid Build Coastguard Worker				if depName == "a" {
341*333d2b36SAndroid Build Coastguard Worker					aCount++
342*333d2b36SAndroid Build Coastguard Worker				}
343*333d2b36SAndroid Build Coastguard Worker			}
344*333d2b36SAndroid Build Coastguard Worker			if aCount != 2 {
345*333d2b36SAndroid Build Coastguard Worker				t.Errorf("Unexpected number of liba dependencies want %v, got %v: %v", 2, aCount, deps)
346*333d2b36SAndroid Build Coastguard Worker			}
347*333d2b36SAndroid Build Coastguard Worker			return
348*333d2b36SAndroid Build Coastguard Worker		}
349*333d2b36SAndroid Build Coastguard Worker	}
350*333d2b36SAndroid Build Coastguard Worker	t.Errorf("libb crate has not been found: %v", crates)
351*333d2b36SAndroid Build Coastguard Worker}
352