Merge changes I329d0fe3,I8af9115b

* changes:
  rust: validate existence of library source
  rust: handle modules with same crate_name
diff --git a/rust/project_json.go b/rust/project_json.go
index 41dd194..8310479 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -75,17 +75,16 @@
 	knownCrates map[string]crateInfo, module android.Module,
 	crate *rustProjectCrate, deps map[string]int) {
 
-	//TODO(tweek): The stdlib dependencies do not appear here. We need to manually add them.
 	ctx.VisitDirectDeps(module, func(child android.Module) {
-		childId, childName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
+		childId, childCrateName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
 		if !ok {
 			return
 		}
-		if _, ok = deps[childName]; ok {
+		if _, ok = deps[ctx.ModuleName(child)]; ok {
 			return
 		}
-		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childName})
-		deps[childName] = childId
+		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childCrateName})
+		deps[ctx.ModuleName(child)] = childId
 	})
 }
 
@@ -106,8 +105,9 @@
 	if !ok {
 		return 0, "", false
 	}
+	moduleName := ctx.ModuleName(module)
 	crateName := rModule.CrateName()
-	if cInfo, ok := knownCrates[crateName]; ok {
+	if cInfo, ok := knownCrates[moduleName]; ok {
 		// We have seen this crate already; merge any new dependencies.
 		crate := project.Crates[cInfo.ID]
 		mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
@@ -115,15 +115,18 @@
 		return cInfo.ID, crateName, true
 	}
 	crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
-	src := rustLib.baseCompiler.Properties.Srcs[0]
-	crate.RootModule = path.Join(ctx.ModuleDir(rModule), src)
+	srcs := rustLib.baseCompiler.Properties.Srcs
+	if len(srcs) == 0 {
+		return 0, "", false
+	}
+	crate.RootModule = path.Join(ctx.ModuleDir(rModule), srcs[0])
 	crate.Edition = rustLib.baseCompiler.edition()
 
 	deps := make(map[string]int)
 	mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
 
 	id := len(project.Crates)
-	knownCrates[crateName] = crateInfo{ID: id, Deps: deps}
+	knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
 	project.Crates = append(project.Crates, crate)
 	// rust-analyzer requires that all crates belong to at least one root:
 	// https://github.com/rust-analyzer/rust-analyzer/issues/4735.
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 6786e72..8521940 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -15,6 +15,7 @@
 package rust
 
 import (
+	"encoding/json"
 	"io/ioutil"
 	"path/filepath"
 	"testing"
@@ -23,20 +24,12 @@
 	"android/soong/cc"
 )
 
-func TestProjectJson(t *testing.T) {
-	bp := `rust_library {
-		  name: "liba",
-		  srcs: ["src/lib.rs"],
-		  crate_name: "a"
-		}` + GatherRequiredDepsForTest()
-	env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
-	fs := map[string][]byte{
-		"foo.rs":     nil,
-		"src/lib.rs": nil,
-	}
-
+// testProjectJson run the generation of rust-project.json. It returns the raw
+// content of the generated file.
+func testProjectJson(t *testing.T, bp string, fs map[string][]byte) []byte {
 	cc.GatherRequiredFilesForTest(fs)
 
+	env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
 	config := android.TestArchConfig(buildDir, env, bp, fs)
 	ctx := CreateTestContext()
 	ctx.Register(config)
@@ -48,8 +41,131 @@
 	// The JSON file is generated via WriteFileToOutputDir. Therefore, it
 	// won't appear in the Output of the TestingSingleton. Manually verify
 	// it exists.
-	_, err := ioutil.ReadFile(filepath.Join(buildDir, "rust-project.json"))
+	content, err := ioutil.ReadFile(filepath.Join(buildDir, rustProjectJsonFileName))
 	if err != nil {
 		t.Errorf("rust-project.json has not been generated")
 	}
+	return content
+}
+
+// validateJsonCrates validates that content follows the basic structure of
+// rust-project.json. It returns the crates attribute if the validation
+// succeeded.
+// It uses an empty interface instead of relying on a defined structure to
+// avoid a strong dependency on our implementation.
+func validateJsonCrates(t *testing.T, rawContent []byte) []interface{} {
+	var content interface{}
+	err := json.Unmarshal(rawContent, &content)
+	if err != nil {
+		t.Errorf("Unable to parse the rust-project.json as JSON: %v", err)
+	}
+	root, ok := content.(map[string]interface{})
+	if !ok {
+		t.Errorf("Unexpected JSON format: %v", content)
+	}
+	if _, ok = root["crates"]; !ok {
+		t.Errorf("No crates attribute in rust-project.json: %v", root)
+	}
+	crates, ok := root["crates"].([]interface{})
+	if !ok {
+		t.Errorf("Unexpected crates format: %v", root["crates"])
+	}
+	return crates
+}
+
+func TestProjectJsonDep(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba",
+		srcs: ["a/src/lib.rs"],
+		crate_name: "a"
+	}
+	rust_library {
+		name: "libb",
+		srcs: ["b/src/lib.rs"],
+		crate_name: "b",
+		rlibs: ["liba"],
+	}
+	` + GatherRequiredDepsForTest()
+	fs := map[string][]byte{
+		"a/src/lib.rs": nil,
+		"b/src/lib.rs": nil,
+	}
+	jsonContent := testProjectJson(t, bp, fs)
+	validateJsonCrates(t, jsonContent)
+}
+
+func TestProjectJsonBindGen(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba",
+		srcs: ["src/lib.rs"],
+		rlibs: ["libbindings"],
+		crate_name: "a"
+	}
+	rust_bindgen {
+		name: "libbindings",
+		crate_name: "bindings",
+		source_stem: "bindings",
+		host_supported: true,
+		wrapper_src: "src/any.h",
+	}
+	` + GatherRequiredDepsForTest()
+	fs := map[string][]byte{
+		"src/lib.rs": nil,
+	}
+	jsonContent := testProjectJson(t, bp, fs)
+	validateJsonCrates(t, jsonContent)
+}
+
+func TestProjectJsonMultiVersion(t *testing.T) {
+	bp := `
+	rust_library {
+		name: "liba1",
+		srcs: ["a1/src/lib.rs"],
+		crate_name: "a"
+	}
+	rust_library {
+		name: "liba2",
+		srcs: ["a2/src/lib.rs"],
+		crate_name: "a",
+	}
+	rust_library {
+		name: "libb",
+		srcs: ["b/src/lib.rs"],
+		crate_name: "b",
+		rustlibs: ["liba1", "liba2"],
+	}
+	` + GatherRequiredDepsForTest()
+	fs := map[string][]byte{
+		"a1/src/lib.rs": nil,
+		"a2/src/lib.rs": nil,
+		"b/src/lib.rs":  nil,
+	}
+	jsonContent := testProjectJson(t, bp, fs)
+	crates := validateJsonCrates(t, jsonContent)
+	for _, crate := range crates {
+		c := crate.(map[string]interface{})
+		if c["root_module"] == "b/src/lib.rs" {
+			deps, ok := c["deps"].([]interface{})
+			if !ok {
+				t.Errorf("Unexpected format for deps: %v", c["deps"])
+			}
+			aCount := 0
+			for _, dep := range deps {
+				d, ok := dep.(map[string]interface{})
+				if !ok {
+					t.Errorf("Unexpected format for dep: %v", dep)
+				}
+				if d["name"] == "a" {
+					aCount++
+				}
+			}
+			if aCount != 2 {
+				t.Errorf("Unexpected number of liba dependencies want %v, got %v: %v", 2, aCount, deps)
+			}
+			return
+		}
+	}
+	t.Errorf("libb crate has not been found: %v", crates)
 }
diff --git a/rust/testing.go b/rust/testing.go
index 83b2828..925b02c 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -44,7 +44,28 @@
                                 },
 				host_supported: true,
 		}
-
+		rust_prebuilt_library {
+				name: "libstd_x86_64-apple-darwin",
+                                crate_name: "std",
+                                rlib: {
+                                    srcs: ["libstd.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libstd.so"],
+                                },
+				host_supported: true,
+		}
+		rust_prebuilt_library {
+				name: "libtest_x86_64-apple-darwin",
+                                crate_name: "test",
+                                rlib: {
+                                    srcs: ["libtest.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libtest.so"],
+                                },
+				host_supported: true,
+		}
 		//////////////////////////////
 		// Device module requirements