/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.pm;

import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageParser;
import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.os.Bundle;
import android.os.Parcel;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.MediumTest;

import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.junit.Assert.*;

import android.util.ArrayMap;
import android.util.ArraySet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import libcore.io.IoUtils;

@RunWith(AndroidJUnit4.class)
@MediumTest
public class PackageParserTest {
    private File mTmpDir;
    private static final File FRAMEWORK = new File("/system/framework/framework-res.apk");

    @Before
    public void setUp() {
        // Create a new temporary directory for each of our tests.
        mTmpDir = IoUtils.createTemporaryDirectory("PackageParserTest");
    }

    @Test
    public void testParse_noCache() throws Exception {
        PackageParser pp = new CachePackageNameParser();
        PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                false /* useCaches */);
        assertNotNull(pkg);

        pp.setCacheDir(mTmpDir);
        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                false /* useCaches */);
        assertNotNull(pkg);

        // Make sure that we always write out a cache entry for future reference,
        // whether or not we're asked to use caches.
        assertEquals(1, mTmpDir.list().length);
    }

    @Test
    public void testParse_withCache() throws Exception {
        PackageParser pp = new CachePackageNameParser();

        pp.setCacheDir(mTmpDir);
        // The first parse will write this package to the cache.
        pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);

        // Now attempt to parse the package again, should return the
        // cached result.
        PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                true /* useCaches */);
        assertEquals("cache_android", pkg.packageName);

        // Try again, with useCaches == false, shouldn't return the parsed
        // result.
        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
        assertEquals("android", pkg.packageName);

        // We haven't set a cache directory here : the parse should still succeed,
        // just not using the cached results.
        pp = new CachePackageNameParser();
        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
        assertEquals("android", pkg.packageName);

        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
        assertEquals("android", pkg.packageName);
    }

    @Test
    public void test_serializePackage() throws Exception {
        PackageParser pp = new PackageParser();
        pp.setCacheDir(mTmpDir);

        PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
            true /* useCaches */);

        Parcel p = Parcel.obtain();
        pkg.writeToParcel(p, 0 /* flags */);

        p.setDataPosition(0);
        PackageParser.Package deserialized = new PackageParser.Package(p);

        assertPackagesEqual(pkg, deserialized);
    }

    @Test
    public void test_roundTripKnownFields() throws Exception {
        PackageParser.Package pkg = new PackageParser.Package("foo");
        setKnownFields(pkg);

        Parcel p = Parcel.obtain();
        pkg.writeToParcel(p, 0 /* flags */);

        p.setDataPosition(0);
        PackageParser.Package deserialized = new PackageParser.Package(p);
        assertAllFieldsExist(deserialized);
    }

    @Test
    public void test_stringInterning() throws Exception {
        PackageParser.Package pkg = new PackageParser.Package("foo");
        setKnownFields(pkg);

        Parcel p = Parcel.obtain();
        pkg.writeToParcel(p, 0 /* flags */);

        p.setDataPosition(0);
        PackageParser.Package deserialized = new PackageParser.Package(p);

        p.setDataPosition(0);
        PackageParser.Package deserialized2 = new PackageParser.Package(p);

        assertSame(deserialized.packageName, deserialized2.packageName);
        assertSame(deserialized.applicationInfo.permission,
                deserialized2.applicationInfo.permission);
        assertSame(deserialized.requestedPermissions.get(0),
                deserialized2.requestedPermissions.get(0));
        assertSame(deserialized.protectedBroadcasts.get(0),
                deserialized2.protectedBroadcasts.get(0));
        assertSame(deserialized.usesLibraries.get(0),
                deserialized2.usesLibraries.get(0));
        assertSame(deserialized.usesOptionalLibraries.get(0),
                deserialized2.usesOptionalLibraries.get(0));
        assertSame(deserialized.mVersionName, deserialized2.mVersionName);
        assertSame(deserialized.mSharedUserId, deserialized2.mSharedUserId);
    }


    /**
     * A trivial subclass of package parser that only caches the package name, and throws away
     * all other information.
     */
    public static class CachePackageNameParser extends PackageParser {
        @Override
        public byte[] toCacheEntry(Package pkg) {
            return ("cache_" + pkg.packageName).getBytes(StandardCharsets.UTF_8);
        }

        @Override
        public Package fromCacheEntry(byte[] cacheEntry) {
            return new Package(new String(cacheEntry, StandardCharsets.UTF_8));
        }
    }

    // NOTE: The equality assertions below are based on code autogenerated by IntelliJ.

    public static void assertPackagesEqual(PackageParser.Package a, PackageParser.Package b) {
        assertEquals(a.baseRevisionCode, b.baseRevisionCode);
        assertEquals(a.baseHardwareAccelerated, b.baseHardwareAccelerated);
        assertEquals(a.mVersionCode, b.mVersionCode);
        assertEquals(a.mSharedUserLabel, b.mSharedUserLabel);
        assertEquals(a.mPreferredOrder, b.mPreferredOrder);
        assertEquals(a.installLocation, b.installLocation);
        assertEquals(a.coreApp, b.coreApp);
        assertEquals(a.mRequiredForAllUsers, b.mRequiredForAllUsers);
        assertEquals(a.mTrustedOverlay, b.mTrustedOverlay);
        assertEquals(a.mCompileSdkVersion, b.mCompileSdkVersion);
        assertEquals(a.mCompileSdkVersionCodename, b.mCompileSdkVersionCodename);
        assertEquals(a.use32bitAbi, b.use32bitAbi);
        assertEquals(a.packageName, b.packageName);
        assertTrue(Arrays.equals(a.splitNames, b.splitNames));
        assertEquals(a.volumeUuid, b.volumeUuid);
        assertEquals(a.codePath, b.codePath);
        assertEquals(a.baseCodePath, b.baseCodePath);
        assertTrue(Arrays.equals(a.splitCodePaths, b.splitCodePaths));
        assertTrue(Arrays.equals(a.splitRevisionCodes, b.splitRevisionCodes));
        assertTrue(Arrays.equals(a.splitFlags, b.splitFlags));
        assertTrue(Arrays.equals(a.splitPrivateFlags, b.splitPrivateFlags));
        assertApplicationInfoEqual(a.applicationInfo, b.applicationInfo);

        assertEquals(a.permissions.size(), b.permissions.size());
        for (int i = 0; i < a.permissions.size(); ++i) {
            assertPermissionsEqual(a.permissions.get(i), b.permissions.get(i));
            assertSame(a.permissions.get(i).owner, a);
            assertSame(b.permissions.get(i).owner, b);
        }

        assertEquals(a.permissionGroups.size(), b.permissionGroups.size());
        for (int i = 0; i < a.permissionGroups.size(); ++i) {
            assertPermissionGroupsEqual(a.permissionGroups.get(i), b.permissionGroups.get(i));
        }

        assertEquals(a.activities.size(), b.activities.size());
        for (int i = 0; i < a.activities.size(); ++i) {
            assertActivitiesEqual(a.activities.get(i), b.activities.get(i));
        }

        assertEquals(a.receivers.size(), b.receivers.size());
        for (int i = 0; i < a.receivers.size(); ++i) {
            assertActivitiesEqual(a.receivers.get(i), b.receivers.get(i));
        }

        assertEquals(a.providers.size(), b.providers.size());
        for (int i = 0; i < a.providers.size(); ++i) {
            assertProvidersEqual(a.providers.get(i), b.providers.get(i));
        }

        assertEquals(a.services.size(), b.services.size());
        for (int i = 0; i < a.services.size(); ++i) {
            assertServicesEqual(a.services.get(i), b.services.get(i));
        }

        assertEquals(a.instrumentation.size(), b.instrumentation.size());
        for (int i = 0; i < a.instrumentation.size(); ++i) {
            assertInstrumentationEqual(a.instrumentation.get(i), b.instrumentation.get(i));
        }

        assertEquals(a.requestedPermissions, b.requestedPermissions);
        assertEquals(a.protectedBroadcasts, b.protectedBroadcasts);
        assertEquals(a.parentPackage, b.parentPackage);
        assertEquals(a.childPackages, b.childPackages);
        assertEquals(a.libraryNames, b.libraryNames);
        assertEquals(a.usesLibraries, b.usesLibraries);
        assertEquals(a.usesOptionalLibraries, b.usesOptionalLibraries);
        assertTrue(Arrays.equals(a.usesLibraryFiles, b.usesLibraryFiles));
        assertEquals(a.mOriginalPackages, b.mOriginalPackages);
        assertEquals(a.mRealPackage, b.mRealPackage);
        assertEquals(a.mAdoptPermissions, b.mAdoptPermissions);
        assertBundleApproximateEquals(a.mAppMetaData, b.mAppMetaData);
        assertEquals(a.mVersionName, b.mVersionName);
        assertEquals(a.mSharedUserId, b.mSharedUserId);
        assertTrue(Arrays.equals(a.mSignatures, b.mSignatures));
        assertTrue(Arrays.equals(a.mCertificates, b.mCertificates));
        assertTrue(Arrays.equals(a.mLastPackageUsageTimeInMills, b.mLastPackageUsageTimeInMills));
        assertEquals(a.mExtras, b.mExtras);
        assertEquals(a.mRestrictedAccountType, b.mRestrictedAccountType);
        assertEquals(a.mRequiredAccountType, b.mRequiredAccountType);
        assertEquals(a.mOverlayTarget, b.mOverlayTarget);
        assertEquals(a.mSigningKeys, b.mSigningKeys);
        assertEquals(a.mUpgradeKeySets, b.mUpgradeKeySets);
        assertEquals(a.mKeySetMapping, b.mKeySetMapping);
        assertEquals(a.cpuAbiOverride, b.cpuAbiOverride);
        assertTrue(Arrays.equals(a.restrictUpdateHash, b.restrictUpdateHash));
    }

    private static void assertBundleApproximateEquals(Bundle a, Bundle b) {
        if (a == b) {
            return;
        }

        // Force the bundles to be unparceled.
        a.getBoolean("foo");
        b.getBoolean("foo");

        assertEquals(a.toString(), b.toString());
    }

    private static void assertComponentsEqual(PackageParser.Component<?> a,
                                              PackageParser.Component<?> b) {
        assertEquals(a.className, b.className);
        assertBundleApproximateEquals(a.metaData, b.metaData);
        assertEquals(a.getComponentName(), b.getComponentName());

        if (a.intents != null && b.intents != null) {
            assertEquals(a.intents.size(), b.intents.size());
        } else if (a.intents == null || b.intents == null) {
            return;
        }

        for (int i = 0; i < a.intents.size(); ++i) {
            PackageParser.IntentInfo aIntent = a.intents.get(i);
            PackageParser.IntentInfo bIntent = b.intents.get(i);

            assertEquals(aIntent.hasDefault, bIntent.hasDefault);
            assertEquals(aIntent.labelRes, bIntent.labelRes);
            assertEquals(aIntent.nonLocalizedLabel, bIntent.nonLocalizedLabel);
            assertEquals(aIntent.icon, bIntent.icon);
            assertEquals(aIntent.logo, bIntent.logo);
            assertEquals(aIntent.banner, bIntent.banner);
            assertEquals(aIntent.preferred, bIntent.preferred);
        }
    }

    private static void assertPermissionsEqual(PackageParser.Permission a,
                                               PackageParser.Permission b) {
        assertComponentsEqual(a, b);
        assertEquals(a.tree, b.tree);

        // Verify basic flags in PermissionInfo to make sure they're consistent. We don't perform
        // a full structural equality here because the code that serializes them isn't parser
        // specific and is tested elsewhere.
        assertEquals(a.info.protectionLevel, b.info.protectionLevel);
        assertEquals(a.info.group, b.info.group);
        assertEquals(a.info.flags, b.info.flags);

        if (a.group != null && b.group != null) {
            assertPermissionGroupsEqual(a.group, b.group);
        } else if (a.group != null || b.group != null) {
            throw new AssertionError();
        }
    }

    private static void assertInstrumentationEqual(PackageParser.Instrumentation a,
                                                   PackageParser.Instrumentation b) {
        assertComponentsEqual(a, b);

        // Sanity check for InstrumentationInfo.
        assertEquals(a.info.targetPackage, b.info.targetPackage);
        assertEquals(a.info.targetProcesses, b.info.targetProcesses);
        assertEquals(a.info.sourceDir, b.info.sourceDir);
        assertEquals(a.info.publicSourceDir, b.info.publicSourceDir);
    }

    private static void assertServicesEqual(PackageParser.Service a, PackageParser.Service b) {
        assertComponentsEqual(a, b);

        // Sanity check for ServiceInfo.
        assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo);
        assertEquals(a.info.name, b.info.name);
    }

    private static void assertProvidersEqual(PackageParser.Provider a, PackageParser.Provider b) {
        assertComponentsEqual(a, b);

        // Sanity check for ProviderInfo
        assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo);
        assertEquals(a.info.name, b.info.name);
    }

    private static void assertActivitiesEqual(PackageParser.Activity a, PackageParser.Activity b) {
        assertComponentsEqual(a, b);

        // Sanity check for ActivityInfo.
        assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo);
        assertEquals(a.info.name, b.info.name);
    }

    private static void assertPermissionGroupsEqual(PackageParser.PermissionGroup a,
                                                    PackageParser.PermissionGroup b) {
        assertComponentsEqual(a, b);

        // Sanity check for PermissionGroupInfo.
        assertEquals(a.info.name, b.info.name);
        assertEquals(a.info.descriptionRes, b.info.descriptionRes);
    }

    private static void assertApplicationInfoEqual(ApplicationInfo a, ApplicationInfo that) {
        assertEquals(a.descriptionRes, that.descriptionRes);
        assertEquals(a.theme, that.theme);
        assertEquals(a.fullBackupContent, that.fullBackupContent);
        assertEquals(a.uiOptions, that.uiOptions);
        assertEquals(a.flags, that.flags);
        assertEquals(a.privateFlags, that.privateFlags);
        assertEquals(a.requiresSmallestWidthDp, that.requiresSmallestWidthDp);
        assertEquals(a.compatibleWidthLimitDp, that.compatibleWidthLimitDp);
        assertEquals(a.largestWidthLimitDp, that.largestWidthLimitDp);
        assertEquals(a.nativeLibraryRootRequiresIsa, that.nativeLibraryRootRequiresIsa);
        assertEquals(a.uid, that.uid);
        assertEquals(a.minSdkVersion, that.minSdkVersion);
        assertEquals(a.targetSdkVersion, that.targetSdkVersion);
        assertEquals(a.versionCode, that.versionCode);
        assertEquals(a.enabled, that.enabled);
        assertEquals(a.enabledSetting, that.enabledSetting);
        assertEquals(a.installLocation, that.installLocation);
        assertEquals(a.networkSecurityConfigRes, that.networkSecurityConfigRes);
        assertEquals(a.taskAffinity, that.taskAffinity);
        assertEquals(a.permission, that.permission);
        assertEquals(a.processName, that.processName);
        assertEquals(a.className, that.className);
        assertEquals(a.manageSpaceActivityName, that.manageSpaceActivityName);
        assertEquals(a.backupAgentName, that.backupAgentName);
        assertEquals(a.volumeUuid, that.volumeUuid);
        assertEquals(a.scanSourceDir, that.scanSourceDir);
        assertEquals(a.scanPublicSourceDir, that.scanPublicSourceDir);
        assertEquals(a.sourceDir, that.sourceDir);
        assertEquals(a.publicSourceDir, that.publicSourceDir);
        assertTrue(Arrays.equals(a.splitSourceDirs, that.splitSourceDirs));
        assertTrue(Arrays.equals(a.splitPublicSourceDirs, that.splitPublicSourceDirs));
        assertTrue(Arrays.equals(a.resourceDirs, that.resourceDirs));
        assertEquals(a.seInfo, that.seInfo);
        assertTrue(Arrays.equals(a.sharedLibraryFiles, that.sharedLibraryFiles));
        assertEquals(a.dataDir, that.dataDir);
        assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir);
        assertEquals(a.credentialProtectedDataDir, that.credentialProtectedDataDir);
        assertEquals(a.nativeLibraryDir, that.nativeLibraryDir);
        assertEquals(a.secondaryNativeLibraryDir, that.secondaryNativeLibraryDir);
        assertEquals(a.nativeLibraryRootDir, that.nativeLibraryRootDir);
        assertEquals(a.primaryCpuAbi, that.primaryCpuAbi);
        assertEquals(a.secondaryCpuAbi, that.secondaryCpuAbi);
    }

    public static void setKnownFields(PackageParser.Package pkg) {
        pkg.baseRevisionCode = 100;
        pkg.baseHardwareAccelerated = true;
        pkg.mVersionCode = 100;
        pkg.mSharedUserLabel = 100;
        pkg.mPreferredOrder = 100;
        pkg.installLocation = 100;
        pkg.coreApp = true;
        pkg.mRequiredForAllUsers = true;
        pkg.mTrustedOverlay = true;
        pkg.use32bitAbi = true;
        pkg.packageName = "foo";
        pkg.splitNames = new String[] { "foo2" };
        pkg.volumeUuid = "foo3";
        pkg.codePath = "foo4";
        pkg.baseCodePath = "foo5";
        pkg.splitCodePaths = new String[] { "foo6" };
        pkg.splitRevisionCodes = new int[] { 100 };
        pkg.splitFlags = new int[] { 100 };
        pkg.splitPrivateFlags = new int[] { 100 };
        pkg.applicationInfo = new ApplicationInfo();

        pkg.permissions.add(new PackageParser.Permission(pkg));
        pkg.permissionGroups.add(new PackageParser.PermissionGroup(pkg));

        final PackageParser.ParseComponentArgs dummy = new PackageParser.ParseComponentArgs(
                pkg, new String[1], 0, 0, 0, 0, 0, 0, null, 0, 0, 0);

        pkg.activities.add(new PackageParser.Activity(dummy, new ActivityInfo()));
        pkg.receivers.add(new PackageParser.Activity(dummy, new ActivityInfo()));
        pkg.providers.add(new PackageParser.Provider(dummy, new ProviderInfo()));
        pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
        pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
        pkg.requestedPermissions.add("foo7");

        pkg.protectedBroadcasts = new ArrayList<>();
        pkg.protectedBroadcasts.add("foo8");

        pkg.parentPackage = new PackageParser.Package("foo9");

        pkg.childPackages = new ArrayList<>();
        pkg.childPackages.add(new PackageParser.Package("bar"));

        pkg.staticSharedLibName = "foo23";
        pkg.staticSharedLibVersion = 100;
        pkg.usesStaticLibraries = new ArrayList<>();
        pkg.usesStaticLibraries.add("foo23");
        pkg.usesStaticLibrariesCertDigests = new String[1][];
        pkg.usesStaticLibrariesCertDigests[0] = new String[] { "digest" };
        pkg.usesStaticLibrariesVersions = new long[] { 100 };

        pkg.libraryNames = new ArrayList<>();
        pkg.libraryNames.add("foo10");

        pkg.usesLibraries = new ArrayList<>();
        pkg.usesLibraries.add("foo11");

        pkg.usesOptionalLibraries = new ArrayList<>();
        pkg.usesOptionalLibraries.add("foo12");

        pkg.usesLibraryFiles = new String[] { "foo13"};

        pkg.mOriginalPackages = new ArrayList<>();
        pkg.mOriginalPackages.add("foo14");

        pkg.mRealPackage = "foo15";

        pkg.mAdoptPermissions = new ArrayList<>();
        pkg.mAdoptPermissions.add("foo16");

        pkg.mAppMetaData = new Bundle();
        pkg.mVersionName = "foo17";
        pkg.mSharedUserId = "foo18";
        pkg.mSignatures = new Signature[] { new Signature(new byte[16]) };
        pkg.mCertificates = new Certificate[][] { new Certificate[] { null }};
        pkg.mExtras = new Bundle();
        pkg.mRestrictedAccountType = "foo19";
        pkg.mRequiredAccountType = "foo20";
        pkg.mOverlayTarget = "foo21";
        pkg.mOverlayPriority = 100;
        pkg.mSigningKeys = new ArraySet<>();
        pkg.mUpgradeKeySets = new ArraySet<>();
        pkg.mKeySetMapping = new ArrayMap<>();
        pkg.cpuAbiOverride = "foo22";
        pkg.restrictUpdateHash = new byte[16];

        pkg.preferredActivityFilters = new ArrayList<>();
        pkg.preferredActivityFilters.add(new PackageParser.ActivityIntentInfo(
                new PackageParser.Activity(dummy, new ActivityInfo())));

        pkg.configPreferences = new ArrayList<>();
        pkg.configPreferences.add(new ConfigurationInfo());

        pkg.reqFeatures = new ArrayList<>();
        pkg.reqFeatures.add(new FeatureInfo());

        pkg.featureGroups = new ArrayList<>();
        pkg.featureGroups.add(new FeatureGroupInfo());

        pkg.mCompileSdkVersionCodename = "foo23";
        pkg.mCompileSdkVersion = 100;
        pkg.mVersionCodeMajor = 100;
    }

    private static void assertAllFieldsExist(PackageParser.Package pkg) throws Exception {
        Field[] fields = PackageParser.Package.class.getDeclaredFields();

        Set<String> nonSerializedFields = new HashSet<>();
        nonSerializedFields.add("mExtras");
        nonSerializedFields.add("packageUsageTimeMillis");

        for (Field f : fields) {
            final Class<?> fieldType = f.getType();

            if (nonSerializedFields.contains(f.getName())) {
                continue;
            }

            if (List.class.isAssignableFrom(fieldType)) {
                // Sanity check for list fields: Assume they're non-null and contain precisely
                // one element.
                List<?> list = (List<?>) f.get(pkg);
                assertNotNull("List was null: " + f, list);
                assertEquals(1, list.size());
            } else if (fieldType.getComponentType() != null) {
                // Sanity check for array fields: Assume they're non-null and contain precisely
                // one element.
                Object array = f.get(pkg);
                assertNotNull(Array.get(array, 0));
            } else if (fieldType == String.class) {
                // String fields: Check that they're set to "foo".
                String value = (String) f.get(pkg);

                assertTrue("Bad value for field: " + f, value != null && value.startsWith("foo"));
            } else if (fieldType == int.class) {
                // int fields: Check that they're set to 100.
                int value = (int) f.get(pkg);
                assertEquals("Bad value for field: " + f, 100, value);
            } else {
                // All other fields: Check that they're set.
                Object o = f.get(pkg);
                assertNotNull("Field was null: " + f, o);
            }
        }
    }
}

