private ModuleSplit buildShard( Collection<ModuleEntry> entriesByPath, Collection<ModuleEntry> mergedDexFiles, ApkTargeting splitTargeting, AndroidManifest androidManifest, Optional<ResourceTable> mergedResourceTable) { ImmutableList<ModuleEntry> entries = ImmutableList.<ModuleEntry>builder().addAll(entriesByPath).addAll(mergedDexFiles).build(); ModuleSplit.Builder shard = ModuleSplit.builder() .setAndroidManifest(androidManifest) .setEntries(entries) .setApkTargeting(splitTargeting) .setSplitType(SplitType.STANDALONE) // We don't care about the following properties for shards. The values are set just to // satisfy contract of @AutoValue.Builder. // `nativeConfig` is optional and therefore not being set. .setMasterSplit(false) .setModuleName(BASE_MODULE_NAME) .setVariantTargeting(VariantTargeting.getDefaultInstance()); mergedResourceTable.ifPresent(shard::setResourceTable); return shard.build(); }
@Test public void apkMatch_withModuleNameFiltering_instantApks_checksModuleName_isEmpty() { DeviceSpec device = deviceWithSdk(21); ZipPath apk = ZipPath.create("master-de-fr.apk"); BuildApksResult buildApksResult = buildApksResult( createVariant( VariantTargeting.getDefaultInstance(), splitApkSet( /* moduleName= */ "base", splitApkDescription(ApkTargeting.getDefaultInstance(), apk)))); Optional<ImmutableSet<String>> allModules = Optional.empty(); assertThat(new ApkMatcher(device, allModules, MATCH_INSTANT).getMatchingApks(buildApksResult)) .isEmpty(); Optional<ImmutableSet<String>> baseModuleOnly = Optional.of(ImmutableSet.of("base")); assertThat( new ApkMatcher(device, baseModuleOnly, MATCH_INSTANT).getMatchingApks(buildApksResult)) .isEmpty(); Optional<ImmutableSet<String>> featureModuleOnly = Optional.of(ImmutableSet.of("feature")); // No matching instant variant assertThat( new ApkMatcher(device, featureModuleOnly, MATCH_INSTANT) .getMatchingApks(buildApksResult)) .isEmpty(); }
buildApksResult( createVariant( VariantTargeting.getDefaultInstance(), splitApkSet( /* moduleName= */ "base",
.addVariant( createVariant( VariantTargeting.getDefaultInstance(), createSplitApkSet( "base",
buildApksResult( createVariant( VariantTargeting.getDefaultInstance(), splitApkSet( /* moduleName= */ "base",
.setMasterSplit(false) .setAndroidManifest(AndroidManifest.create(androidManifest("com.test.app"))) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); ModuleSplit assetsSplit2 = .setMasterSplit(false) .setAndroidManifest(AndroidManifest.create(androidManifest("com.test.app"))) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); BundleModule bundleModule =
.setModuleName(BundleModuleName.create("base")) .setApkTargeting(ApkTargeting.getDefaultInstance()) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); ModuleSplit assetSlice = .setModuleName(BundleModuleName.create("some_assets")) .setApkTargeting(ApkTargeting.getDefaultInstance()) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build();
buildApksResult( createVariant( VariantTargeting.getDefaultInstance(), splitApkSet( /* moduleName= */ "base",
@Test public void apkMatch_withModuleNameFiltering_instantApks_checksModuleName_exists() { DeviceSpec device = deviceWithSdk(21); ZipPath apk = ZipPath.create("master-de-fr.apk"); BuildApksResult buildApksResult = buildApksResult( createVariant( VariantTargeting.getDefaultInstance(), splitApkSet( /* moduleName= */ "base", instantApkDescription(ApkTargeting.getDefaultInstance(), apk)))); Optional<ImmutableSet<String>> allModules = Optional.empty(); assertThat(new ApkMatcher(device, allModules, MATCH_INSTANT).getMatchingApks(buildApksResult)) .containsExactly(apk); Optional<ImmutableSet<String>> baseModuleOnly = Optional.of(ImmutableSet.of("base")); assertThat( new ApkMatcher(device, baseModuleOnly, MATCH_INSTANT).getMatchingApks(buildApksResult)) .containsExactly(apk); Optional<ImmutableSet<String>> unknownModuleOnly = Optional.of(ImmutableSet.of("unknown_module")); ValidationException exception = assertThrows( ValidationException.class, () -> new ApkMatcher(device, unknownModuleOnly, MATCH_INSTANT) .getMatchingApks(buildApksResult)); assertThat(exception) .hasMessageThat() .contains("The APK Set archive does not contain the following modules: [unknown_module]"); }
.setMasterSplit(false) .setAndroidManifest(AndroidManifest.create(androidManifest("com.test.app"))) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); ModuleSplit assetsSplit2 =
@Test public void nonExistentModule_throws() throws Exception { ZipPath apkLBase = ZipPath.create("apkL-base.apk"); BuildApksResult tableOfContentsProto = BuildApksResult.newBuilder() .addVariant( createVariant( VariantTargeting.getDefaultInstance(), createSplitApkSet( "base", createMasterApkDescription(ApkTargeting.getDefaultInstance(), apkLBase)))) .build(); Path apksArchiveFile = createApksArchiveFile(tableOfContentsProto, tmpDir.resolve("bundle.apks")); Path deviceSpecFile = createDeviceSpecFile(deviceWithSdk(21), tmpDir.resolve("device.json")); ExtractApksCommand command = ExtractApksCommand.fromFlags( new FlagParser() .parse( "--device-spec=" + deviceSpecFile, "--apks=" + apksArchiveFile, "--modules=unknown_module")); Throwable exception = assertThrows(ValidationException.class, () -> command.execute()); assertThat(exception) .hasMessageThat() .contains("The APK Set archive does not contain the following modules: [unknown_module]"); }
private static ModuleSplit createModuleSplit( String moduleName, String splitId, boolean masterSplit, SplitType splitType, @Nullable LanguageTargeting languageTargeting) { return ModuleSplit.builder() .setAndroidManifest( AndroidManifest.create(androidManifest(PACKAGE_NAME)) .toEditor() .setSplitId(splitId) .save()) .setEntries(ImmutableList.of()) .setMasterSplit(masterSplit) .setSplitType(splitType) .setModuleName(BundleModuleName.create(moduleName)) .setApkTargeting( languageTargeting == null ? ApkTargeting.getDefaultInstance() : ApkTargeting.newBuilder().setLanguageTargeting(languageTargeting).build()) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); } }
@Test public void apexModuleMultiAbiSplitSuffixAndName() { ModuleSplit resSplit = ModuleSplit.builder() .setModuleName(BundleModuleName.create("base")) .setEntries(ImmutableList.of()) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .setApkTargeting( apkMultiAbiTargeting( multiAbiTargeting( ImmutableSet.of( ImmutableSet.of(AbiAlias.X86_64, AbiAlias.X86), ImmutableSet.of(AbiAlias.ARM64_V8A, AbiAlias.ARMEABI_V7A)), ImmutableSet.of()))) .setMasterSplit(false) .setAndroidManifest(AndroidManifest.create(androidManifest("com.test.app"))) .build(); resSplit = resSplit.writeSplitIdInManifest(resSplit.getSuffix()); assertThat(resSplit.getAndroidManifest().getSplitId()) .hasValue("config.x86_64.x86_arm64_v8a.armeabi_v7a"); }
@Test public void buildApksResult_readTableOfContents() throws Exception { ZipPath apkLBase = ZipPath.create("apkL-base.apk"); BuildApksResult tableOfContentsProto = BuildApksResult.newBuilder() .addVariant( createVariant( VariantTargeting.getDefaultInstance(), createSplitApkSet( "base", createMasterApkDescription(ApkTargeting.getDefaultInstance(), apkLBase)))) .build(); Path apksArchiveFile = createApksArchiveFile(tableOfContentsProto, tmpDir.resolve("bundle.apks")); BuildApksResult buildApksResult = readTableOfContents(apksArchiveFile); assertThat(buildApksResult).isEqualTo(tableOfContentsProto); }
@Test public void mergingFromMultipleVariants_throws() { ModuleSplit split1 = createModuleSplitBuilder().setVariantTargeting(lPlusVariantTargeting()).build(); ModuleSplit split2 = createModuleSplitBuilder() .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); Throwable exception = assertThrows( IllegalArgumentException.class, () -> new SameTargetingMerger().merge(ImmutableList.of(split1, split2))); assertThat(exception) .hasMessageThat() .contains("SameTargetingMerger doesn't support merging splits from different variants."); } }
public static ModuleSplit fromAssetBundleModule(BundleModule bundleModule) { checkArgument( bundleModule.getModuleType().equals(ModuleType.ASSET_MODULE), "Expected an Asset Module, got %s", bundleModule.getModuleType()); ModuleSplit.Builder splitBuilder = ModuleSplit.builder() .setModuleName(bundleModule.getName()) .setEntries(bundleModule.getEntries().asList()) .setAndroidManifest(bundleModule.getAndroidManifest()) .setMasterSplit(true) .setSplitType(SplitType.ASSET_SLICE) .setApkTargeting(ApkTargeting.getDefaultInstance()) .setVariantTargeting(VariantTargeting.getDefaultInstance()); bundleModule.getAssetsConfig().ifPresent(splitBuilder::setAssetsConfig); return splitBuilder.build(); }
private static ModuleSplit createModuleSplit( AndroidManifest androidManifest, ResourceTable resourceTable, ImmutableList<ModuleEntry> entries) { return ModuleSplit.builder() .setAndroidManifest(androidManifest) .setResourceTable(resourceTable) .setEntries(entries) .setModuleName(BundleModuleName.create(BundleModuleName.BASE_MODULE_NAME)) .setApkTargeting(ApkTargeting.getDefaultInstance()) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .setMasterSplit(true) .build(); }
/** Creates a table of content matching all devices to a given apkPath. */ private static BuildApksResult createSimpleTableOfContent(ZipPath apkPath) { return BuildApksResult.newBuilder() .addVariant( createVariantForSingleSplitApk( VariantTargeting.getDefaultInstance(), ApkTargeting.getDefaultInstance(), apkPath)) .build(); }
private static ModuleSplit createModuleSplit(SplitType splitType) { return ModuleSplit.builder() .setAndroidManifest(AndroidManifest.create(androidManifest("com.test.app"))) .setEntries(ImmutableList.of()) .setMasterSplit(true) .setSplitType(splitType) .setModuleName(BundleModuleName.create("base")) .setApkTargeting(ApkTargeting.getDefaultInstance()) .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); } }
private static ModuleSplit clearVariantTargeting(ModuleSplit moduleSplit) { return moduleSplit .toBuilder() .setVariantTargeting(VariantTargeting.getDefaultInstance()) .build(); }