/*
 * Copyright (C) 2017 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.dex;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.content.pm.ApplicationInfo;
import android.content.pm.SharedLibraryInfo;
import android.util.SparseArray;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import dalvik.system.DelegateLastClassLoader;
import dalvik.system.DexClassLoader;
import dalvik.system.PathClassLoader;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class DexoptUtilsTest {
    private static final String DEX_CLASS_LOADER_NAME = DexClassLoader.class.getName();
    private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
    private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
            DelegateLastClassLoader.class.getName();

    private static class TestData {
        ApplicationInfo info;
        boolean[] pathsWithCode;
    }

    private TestData createMockApplicationInfo(String baseClassLoader, boolean addSplits,
            boolean addSplitDependencies) {
        ApplicationInfo ai = new ApplicationInfo();
        String codeDir = "/data/app/mock.android.com";
        ai.setBaseCodePath(codeDir + "/base.dex");
        ai.classLoaderName = baseClassLoader;
        ai.privateFlags = ai.privateFlags | ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
        boolean[] pathsWithCode;
        if (!addSplits) {
            pathsWithCode = new boolean[] {true};
        } else {
            pathsWithCode = new boolean[9];
            Arrays.fill(pathsWithCode, true);
            pathsWithCode[7] = false;  // config split

            ai.setSplitCodePaths(new String[]{
                    codeDir + "/base-1.dex",
                    codeDir + "/base-2.dex",
                    codeDir + "/base-3.dex",
                    codeDir + "/base-4.dex",
                    codeDir + "/base-5.dex",
                    codeDir + "/base-6.dex",
                    codeDir + "/config-split-7.dex",
                    codeDir + "/feature-no-deps.dex"});

            ai.splitClassLoaderNames = new String[]{
                    DELEGATE_LAST_CLASS_LOADER_NAME,
                    DELEGATE_LAST_CLASS_LOADER_NAME,
                    PATH_CLASS_LOADER_NAME,
                    DEX_CLASS_LOADER_NAME,
                    PATH_CLASS_LOADER_NAME,
                    null,   // A null class loader name should default to PathClassLoader.
                    null,   // The config split gets a null class loader.
                    null};  // The feature split with no dependency and no specified class loader.
            if (addSplitDependencies) {
                ai.splitDependencies = new SparseArray<>(ai.splitClassLoaderNames.length + 1);
                ai.splitDependencies.put(0, new int[] {-1}); // base has no dependency
                ai.splitDependencies.put(1, new int[] {2}); // split 1 depends on 2
                ai.splitDependencies.put(2, new int[] {4}); // split 2 depends on 4
                ai.splitDependencies.put(3, new int[] {4}); // split 3 depends on 4
                ai.splitDependencies.put(4, new int[] {0}); // split 4 depends on base
                ai.splitDependencies.put(5, new int[] {0}); // split 5 depends on base
                ai.splitDependencies.put(6, new int[] {5}); // split 6 depends on 5
                // Do not add the config split to the dependency list.
                // Do not add the feature split with no dependency to the dependency list.
            }
        }
        TestData data = new TestData();
        data.info = ai;
        data.pathsWithCode = pathsWithCode;
        return data;
    }

    private List<SharedLibraryInfo> createMockSharedLibrary(String [] sharedLibrary) {
        SharedLibraryInfo info = new SharedLibraryInfo(null, null, Arrays.asList(sharedLibrary),
                null, 0L, SharedLibraryInfo.TYPE_STATIC, null, null, null);
        ArrayList<SharedLibraryInfo> libraries = new ArrayList<>();
        libraries.add(info);
        return libraries;
    }

    @Test
    public void testSplitChain() {
        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
        assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}",
                contexts[1]);
        assertEquals("DLC[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[2]);
        assertEquals("PCL[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[3]);
        assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[4]);
        assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[5]);
        assertEquals("PCL[];PCL[base-5.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[6]);
        assertEquals(null, contexts[7]);  // config split
        assertEquals("PCL[]", contexts[8]);  // feature split with no dependency
    }

    @Test
    public void testSplitChainNoSplitDependencies() {
        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, false);
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
        assertEquals("PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[1]);
        assertEquals("PCL[base.dex:base-1.dex]{PCL[a.dex:b.dex]}", contexts[2]);
        assertEquals("PCL[base.dex:base-1.dex:base-2.dex]{PCL[a.dex:b.dex]}", contexts[3]);
        assertEquals(
                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex]{PCL[a.dex:b.dex]}",
                contexts[4]);
        assertEquals(
                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex]{PCL[a.dex:b.dex]}",
                contexts[5]);
        assertEquals(
                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex]{PCL[a.dex:b.dex]}",
                contexts[6]);
        assertEquals(null, contexts[7]);  // config split
        assertEquals(
                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex:base-6.dex:config-split-7.dex]{PCL[a.dex:b.dex]}",
                contexts[8]);  // feature split with no dependency
    }

    @Test
    public void testSplitChainNoIsolationNoSharedLibrary() {
        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
        data.info.privateFlags = data.info.privateFlags
                & (~ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING);
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, null, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals("PCL[]", contexts[0]);
        assertEquals("PCL[base.dex]", contexts[1]);
        assertEquals("PCL[base.dex:base-1.dex]", contexts[2]);
        assertEquals("PCL[base.dex:base-1.dex:base-2.dex]", contexts[3]);
        assertEquals("PCL[base.dex:base-1.dex:base-2.dex:base-3.dex]", contexts[4]);
        assertEquals("PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex]", contexts[5]);
        assertEquals(
                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex]",
                contexts[6]);
        assertEquals(null, contexts[7]);  // config split
        assertEquals(
                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex:base-6.dex:config-split-7.dex]",
                contexts[8]);  // feature split with no dependency
    }

    @Test
    public void testSplitChainNoSharedLibraries() {
        TestData data = createMockApplicationInfo(
                DELEGATE_LAST_CLASS_LOADER_NAME, true, true);
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, null, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals("DLC[]", contexts[0]);
        assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];DLC[base.dex]", contexts[1]);
        assertEquals("DLC[];PCL[base-4.dex];DLC[base.dex]", contexts[2]);
        assertEquals("PCL[];PCL[base-4.dex];DLC[base.dex]", contexts[3]);
        assertEquals("PCL[];DLC[base.dex]", contexts[4]);
        assertEquals("PCL[];DLC[base.dex]", contexts[5]);
        assertEquals("PCL[];PCL[base-5.dex];DLC[base.dex]", contexts[6]);
        assertEquals(null, contexts[7]);  // config split
        assertEquals("PCL[]", contexts[8]);  // feature split with no dependency
    }

    @Test
    public void testSplitChainWithNullPrimaryClassLoader() {
        // A null classLoaderName should mean PathClassLoader.
        TestData data = createMockApplicationInfo(null, true, true);
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
        assertEquals(
                "DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}",
                contexts[1]);
        assertEquals("DLC[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[2]);
        assertEquals("PCL[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[3]);
        assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[4]);
        assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[5]);
        assertEquals("PCL[];PCL[base-5.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[6]);
        assertEquals(null, contexts[7]);  // config split
        assertEquals("PCL[]", contexts[8]);  // feature split with no dependency
    }

    @Test
    public void tesNoSplits() {
        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(1, contexts.length);
        assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
    }

    @Test
    public void tesNoSplitsNullClassLoaderName() {
        TestData data = createMockApplicationInfo(null, false, false);
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(1, contexts.length);
        assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]);
    }

    @Test
    public void tesNoSplitDelegateLast() {
        TestData data = createMockApplicationInfo(
                DELEGATE_LAST_CLASS_LOADER_NAME, false, false);
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(1, contexts.length);
        assertEquals("DLC[]{PCL[a.dex:b.dex]}", contexts[0]);
    }

    @Test
    public void tesNoSplitsNoSharedLibraries() {
        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, null, data.pathsWithCode);

        assertEquals(1, contexts.length);
        assertEquals("PCL[]", contexts[0]);
    }

    @Test
    public void tesNoSplitDelegateLastNoSharedLibraries() {
        TestData data = createMockApplicationInfo(
                DELEGATE_LAST_CLASS_LOADER_NAME, false, false);
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, null, data.pathsWithCode);

        assertEquals(1, contexts.length);
        assertEquals("DLC[]", contexts[0]);
    }

    @Test
    public void testContextWithNoCode() {
        TestData data = createMockApplicationInfo(null, true, false);
        Arrays.fill(data.pathsWithCode, false);

        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals(null, contexts[0]);
        assertEquals(null, contexts[1]);
        assertEquals(null, contexts[2]);
        assertEquals(null, contexts[3]);
        assertEquals(null, contexts[4]);
        assertEquals(null, contexts[5]);
        assertEquals(null, contexts[6]);
        assertEquals(null, contexts[7]);
    }

    @Test
    public void testContextBaseNoCode() {
        TestData data = createMockApplicationInfo(null, true, true);
        data.pathsWithCode[0] = false;
        List<SharedLibraryInfo> sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"});
        String[] contexts = DexoptUtils.getClassLoaderContexts(
                data.info, sharedLibrary, data.pathsWithCode);

        assertEquals(9, contexts.length);
        assertEquals(null, contexts[0]);
        assertEquals(
                "DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}",
                contexts[1]);
        assertEquals("DLC[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[2]);
        assertEquals("PCL[];PCL[base-4.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[3]);
        assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[4]);
        assertEquals("PCL[];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[5]);
        assertEquals("PCL[];PCL[base-5.dex];PCL[base.dex]{PCL[a.dex:b.dex]}", contexts[6]);
        assertEquals(null, contexts[7]);
    }

    @Test
    public void testSharedLibraryContext() {
        SharedLibraryInfo sharedLibrary =
                createMockSharedLibrary(new String[] {"a.dex", "b.dex"}).get(0);
        String context = DexoptUtils.getClassLoaderContext(sharedLibrary);
        assertEquals("PCL[]", context);

        SharedLibraryInfo otherSharedLibrary =
                createMockSharedLibrary(new String[] {"c.dex"}).get(0);
        otherSharedLibrary.addDependency(sharedLibrary);
        context = DexoptUtils.getClassLoaderContext(otherSharedLibrary);
        assertEquals("PCL[]{PCL[a.dex:b.dex]}", context);
    }

    @Test
    public void testProcessContextForDexLoad() {
        List<String> classLoaders = Arrays.asList(
                DELEGATE_LAST_CLASS_LOADER_NAME,
                PATH_CLASS_LOADER_NAME,
                PATH_CLASS_LOADER_NAME);
        List<String> classPaths = Arrays.asList(
                String.join(File.pathSeparator, "foo.dex", "bar.dex"),
                String.join(File.pathSeparator, "parent1.dex"),
                String.join(File.pathSeparator, "parent2.dex", "parent3.dex"));
        String[] context = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
        assertNotNull(context);
        assertEquals(2, context.length);
        assertEquals("DLC[];PCL[parent1.dex];PCL[parent2.dex:parent3.dex]", context[0]);
        assertEquals("DLC[foo.dex];PCL[parent1.dex];PCL[parent2.dex:parent3.dex]", context[1]);
    }

    @Test
    public void testProcessContextForDexLoadSingleElement() {
        List<String> classLoaders = Arrays.asList(PATH_CLASS_LOADER_NAME);
        List<String> classPaths = Arrays.asList(
                String.join(File.pathSeparator, "foo.dex", "bar.dex", "zoo.dex"));
        String[] context = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
        assertNotNull(context);
        assertEquals(3, context.length);
        assertEquals("PCL[]", context[0]);
        assertEquals("PCL[foo.dex]", context[1]);
        assertEquals("PCL[foo.dex:bar.dex]", context[2]);
    }

    @Test
    public void testProcessContextForDexLoadUnsupported() {
        List<String> classLoaders = Arrays.asList(
                DELEGATE_LAST_CLASS_LOADER_NAME,
                "unsupported.class.loader");
        List<String> classPaths = Arrays.asList(
                String.join(File.pathSeparator, "foo.dex", "bar.dex"),
                String.join(File.pathSeparator, "parent1.dex"));
        String[] context = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
        assertNull(context);
    }

    @Test
    public void testProcessContextForDexLoadNoClassPath() {
        List<String> classLoaders = Arrays.asList(
                DELEGATE_LAST_CLASS_LOADER_NAME,
                PATH_CLASS_LOADER_NAME);
        List<String> classPaths = Arrays.asList(
                String.join(File.pathSeparator, "foo.dex", "bar.dex"),
                null);
        String[] context = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
        assertNull(context);
    }

    @Test
    public void testProcessContextForDexLoadIllegalCallEmptyList() {
        boolean gotException = false;
        try {
            DexoptUtils.processContextForDexLoad(Collections.emptyList(), Collections.emptyList());
        } catch (IllegalArgumentException ignore) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    @Test
    public void testProcessContextForDexLoadIllegalCallDifferentSize() {
        boolean gotException = false;
        try {
            DexoptUtils.processContextForDexLoad(Collections.emptyList(), Arrays.asList("a"));
        } catch (IllegalArgumentException ignore) {
            gotException = true;
        }
        assertTrue(gotException);
    }

    @Test
    public void testEncodeClassLoader() {
        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
                "dalvik.system.PathClassLoader"));
        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
                "dalvik.system.DexClassLoader"));
        assertEquals("DLC[xyz]", DexoptUtils.encodeClassLoader("xyz",
                "dalvik.system.DelegateLastClassLoader"));
        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz", null));
        assertEquals("abc[xyz]", DexoptUtils.encodeClassLoader("xyz", "abc"));

        try {
            DexoptUtils.encodeClassLoader(null, "abc");
            fail(); // Exception should be caught.
        } catch (NullPointerException expected) {}
    }

    @Test
    public void testEncodeClassLoaderChain() {
        assertEquals("PCL[a];DLC[b]", DexoptUtils.encodeClassLoaderChain("PCL[a]",
                "DLC[b]"));
        try {
            DexoptUtils.encodeClassLoaderChain("a", null);
            fail(); // exception is expected
        } catch (NullPointerException expected) {}

        try {
            DexoptUtils.encodeClassLoaderChain(null, "b");
            fail(); // exception is expected
        } catch (NullPointerException expected) {}
    }
}
