Add a test to check the intall partitions

cc modules have complex image variant settings. To avoid setting
wrong partitions to modules, add a test to check the install
partition.

Bug: 184885453
Test: m nothing
Change-Id: I080661335f2da7281d6e6a0d2fedd1fcecb4b2cb
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 465283d..e4dfc97 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -244,6 +244,120 @@
 	}
 }
 
+func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) {
+	mod := ctx.ModuleForTests(name, variant).Module().(*Module)
+	partitionDefined := false
+	checkPartition := func(specific bool, partition string) {
+		if specific {
+			if expected != partition && !partitionDefined {
+				// The variant is installed to the 'partition'
+				t.Errorf("%s variant of %q must not be installed to %s partition", variant, name, partition)
+			}
+			partitionDefined = true
+		} else {
+			// The variant is not installed to the 'partition'
+			if expected == partition {
+				t.Errorf("%s variant of %q must be installed to %s partition", variant, name, partition)
+			}
+		}
+	}
+	socSpecific := func(m *Module) bool {
+		return m.SocSpecific() || m.socSpecificModuleContext()
+	}
+	deviceSpecific := func(m *Module) bool {
+		return m.DeviceSpecific() || m.deviceSpecificModuleContext()
+	}
+	productSpecific := func(m *Module) bool {
+		return m.ProductSpecific() || m.productSpecificModuleContext()
+	}
+	systemExtSpecific := func(m *Module) bool {
+		return m.SystemExtSpecific()
+	}
+	checkPartition(socSpecific(mod), "vendor")
+	checkPartition(deviceSpecific(mod), "odm")
+	checkPartition(productSpecific(mod), "product")
+	checkPartition(systemExtSpecific(mod), "system_ext")
+	if !partitionDefined && expected != "system" {
+		t.Errorf("%s variant of %q is expected to be installed to %s partition,"+
+			" but installed to system partition", variant, name, expected)
+	}
+}
+
+func TestInstallPartition(t *testing.T) {
+	t.Helper()
+	ctx := prepareForCcTest.RunTestWithBp(t, `
+		cc_library {
+			name: "libsystem",
+		}
+		cc_library {
+			name: "libsystem_ext",
+			system_ext_specific: true,
+		}
+		cc_library {
+			name: "libproduct",
+			product_specific: true,
+		}
+		cc_library {
+			name: "libvendor",
+			vendor: true,
+		}
+		cc_library {
+			name: "libodm",
+			device_specific: true,
+		}
+		cc_library {
+			name: "liball_available",
+			vendor_available: true,
+			product_available: true,
+		}
+		cc_library {
+			name: "libsystem_ext_all_available",
+			system_ext_specific: true,
+			vendor_available: true,
+			product_available: true,
+		}
+		cc_library {
+			name: "liball_available_odm",
+			odm_available: true,
+			product_available: true,
+		}
+		cc_library {
+			name: "libproduct_vendoravailable",
+			product_specific: true,
+			vendor_available: true,
+		}
+		cc_library {
+			name: "libproduct_odmavailable",
+			product_specific: true,
+			odm_available: true,
+		}
+	`).TestContext
+
+	checkInstallPartition(t, ctx, "libsystem", coreVariant, "system")
+	checkInstallPartition(t, ctx, "libsystem_ext", coreVariant, "system_ext")
+	checkInstallPartition(t, ctx, "libproduct", productVariant, "product")
+	checkInstallPartition(t, ctx, "libvendor", vendorVariant, "vendor")
+	checkInstallPartition(t, ctx, "libodm", vendorVariant, "odm")
+
+	checkInstallPartition(t, ctx, "liball_available", coreVariant, "system")
+	checkInstallPartition(t, ctx, "liball_available", productVariant, "product")
+	checkInstallPartition(t, ctx, "liball_available", vendorVariant, "vendor")
+
+	checkInstallPartition(t, ctx, "libsystem_ext_all_available", coreVariant, "system_ext")
+	checkInstallPartition(t, ctx, "libsystem_ext_all_available", productVariant, "product")
+	checkInstallPartition(t, ctx, "libsystem_ext_all_available", vendorVariant, "vendor")
+
+	checkInstallPartition(t, ctx, "liball_available_odm", coreVariant, "system")
+	checkInstallPartition(t, ctx, "liball_available_odm", productVariant, "product")
+	checkInstallPartition(t, ctx, "liball_available_odm", vendorVariant, "odm")
+
+	checkInstallPartition(t, ctx, "libproduct_vendoravailable", productVariant, "product")
+	checkInstallPartition(t, ctx, "libproduct_vendoravailable", vendorVariant, "vendor")
+
+	checkInstallPartition(t, ctx, "libproduct_odmavailable", productVariant, "product")
+	checkInstallPartition(t, ctx, "libproduct_odmavailable", vendorVariant, "odm")
+}
+
 func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string,
 	isVndkSp bool, extends string, variant string) {
 
diff --git a/cc/image.go b/cc/image.go
index 2af7c9e..ca00ac9 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -49,23 +49,15 @@
 )
 
 func (ctx *moduleContext) ProductSpecific() bool {
-	// Additionally check if this module is inProduct() that means it is a "product" variant of a
-	// module. As well as product specific modules, product variants must be installed to /product.
-	return ctx.ModuleContext.ProductSpecific() || ctx.mod.InProduct()
+	return ctx.ModuleContext.ProductSpecific() || ctx.mod.productSpecificModuleContext()
 }
 
 func (ctx *moduleContext) SocSpecific() bool {
-	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
-	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
-	// unless they have "odm_available: true".
-	return ctx.ModuleContext.SocSpecific() ||
-            (ctx.mod.HasVendorVariant() && ctx.mod.InVendor() && !ctx.mod.VendorVariantToOdm())
+	return ctx.ModuleContext.SocSpecific() || ctx.mod.socSpecificModuleContext()
 }
 
 func (ctx *moduleContext) DeviceSpecific() bool {
-	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
-	return ctx.ModuleContext.DeviceSpecific() ||
-            (ctx.mod.HasVendorVariant() && ctx.mod.InVendor() && ctx.mod.VendorVariantToOdm())
+	return ctx.ModuleContext.DeviceSpecific() || ctx.mod.deviceSpecificModuleContext()
 }
 
 func (ctx *moduleContextImpl) inProduct() bool {
@@ -88,6 +80,24 @@
 	return ctx.mod.InRecovery()
 }
 
+func (c *Module) productSpecificModuleContext() bool {
+	// Additionally check if this module is inProduct() that means it is a "product" variant of a
+	// module. As well as product specific modules, product variants must be installed to /product.
+	return c.InProduct()
+}
+
+func (c *Module) socSpecificModuleContext() bool {
+	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
+	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
+	// unless they have "odm_available: true".
+	return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm()
+}
+
+func (c *Module) deviceSpecificModuleContext() bool {
+	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
+	return c.InVendor() && c.VendorVariantToOdm()
+}
+
 // Returns true when this module is configured to have core and vendor variants.
 func (c *Module) HasVendorVariant() bool {
 	return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available)