// Copyright 2017 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.android.dexer;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.newDirectExecutorService;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.android.dex.Dex;
import com.android.dx.command.dexer.DxContext;
import com.android.dx.dex.DexOptions;
import com.android.dx.dex.cf.CfOptions;
import com.android.dx.dex.file.DexFile;
import com.google.common.collect.Iterables;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/** Tests for {@link DexFileAggregator}. */
@RunWith(JUnit4.class)
public class DexFileAggregatorTest {

  /** Standard .dex file limit on methods and fields. */
  private static final int DEX_LIMIT = 265 * 265;
  private static final int WASTE = 1;

  @Mock private DexFileArchive dest;
  @Captor private ArgumentCaptor<Dex> written;

  private Dex dex;

  @Before
  public void setUp() throws IOException {
    dex = DexFiles.toDex(convertClass(DexFileAggregatorTest.class));
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testClose_emptyWritesNothing() throws Exception {
    DexFileAggregator dexer =
        new DexFileAggregator(
            new DxContext(),
            dest,
            newDirectExecutorService(),
            MultidexStrategy.MINIMAL,
            /*forceJumbo=*/ false,
            DEX_LIMIT,
            WASTE,
            DexFileMergerTest.DEX_PREFIX);
    dexer.close();
    verify(dest, times(0)).addFile(any(ZipEntry.class), any(Dex.class));
  }

  @Test
  public void testAddAndClose_singleInputWritesThatInput() throws Exception {
    DexFileAggregator dexer =
        new DexFileAggregator(
            new DxContext(),
            dest,
            newDirectExecutorService(),
            MultidexStrategy.MINIMAL,
            /*forceJumbo=*/ false,
            0,
            WASTE,
            DexFileMergerTest.DEX_PREFIX);
    dexer.add(dex);
    dexer.close();
    verify(dest).addFile(any(ZipEntry.class), eq(dex));
  }

  @Test
  public void testAddAndClose_forceJumboRewrites() throws Exception {
    DexFileAggregator dexer =
        new DexFileAggregator(
            new DxContext(),
            dest,
            newDirectExecutorService(),
            MultidexStrategy.MINIMAL,
            /*forceJumbo=*/ true,
            0,
            WASTE,
            DexFileMergerTest.DEX_PREFIX);
    dexer.add(dex);
    try {
      dexer.close();
    } catch (IllegalStateException e) {
      assertThat(e).hasMessage("--forceJumbo flag not supported");
      System.err.println("Skipping this test due to missing --forceJumbo support in Android SDK.");
      e.printStackTrace();
      return;
    }

    verify(dest).addFile(any(ZipEntry.class), written.capture());
    assertThat(written.getValue()).isNotEqualTo(dex);
    assertThat(written.getValue().getLength()).isGreaterThan(dex.getLength());
  }

  @Test
  public void testMultidex_underLimitWritesOneShard() throws Exception {
    DexFileAggregator dexer =
        new DexFileAggregator(
            new DxContext(),
            dest,
            newDirectExecutorService(),
            MultidexStrategy.BEST_EFFORT,
            /*forceJumbo=*/ false,
            DEX_LIMIT,
            WASTE,
            DexFileMergerTest.DEX_PREFIX);
    Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
    dexer.add(dex);
    dexer.add(dex2);
    verify(dest, times(0)).addFile(any(ZipEntry.class), any(Dex.class));
    dexer.close();
    verify(dest).addFile(any(ZipEntry.class), written.capture());
    assertThat(Iterables.size(written.getValue().classDefs())).isEqualTo(2);
  }

  @Test
  public void testMultidex_overLimitWritesSecondShard() throws Exception {
    DexFileAggregator dexer =
        new DexFileAggregator(
            new DxContext(),
            dest,
            newDirectExecutorService(),
            MultidexStrategy.BEST_EFFORT,
            /*forceJumbo=*/ false,
            2 /* dex has more than 2 methods and fields */,
            WASTE,
            DexFileMergerTest.DEX_PREFIX);
    Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
    dexer.add(dex);   // classFile is already over limit but we take anything in empty shard
    dexer.add(dex2);  // this should start a new shard
    // Make sure there was one file written and that file is dex
    verify(dest).addFile(any(ZipEntry.class), written.capture());
    assertThat(written.getValue()).isSameAs(dex);
    dexer.close();
    verify(dest).addFile(any(ZipEntry.class), eq(dex2));
  }

  @Test
  public void testMonodex_alwaysWritesSingleShard() throws Exception {
    DexFileAggregator dexer =
        new DexFileAggregator(
            new DxContext(),
            dest,
            newDirectExecutorService(),
            MultidexStrategy.OFF,
            /*forceJumbo=*/ false,
            2 /* dex has more than 2 methods and fields */,
            WASTE,
            DexFileMergerTest.DEX_PREFIX);
    Dex dex2 = DexFiles.toDex(convertClass(ByteStreams.class));
    dexer.add(dex);
    dexer.add(dex2);
    verify(dest, times(0)).addFile(any(ZipEntry.class), any(Dex.class));
    dexer.close();
    verify(dest).addFile(any(ZipEntry.class), written.capture());
    assertThat(Iterables.size(written.getValue().classDefs())).isEqualTo(2);
  }

  private static DexFile convertClass(Class<?> clazz) throws IOException {
    String path = clazz.getName().replace('.', '/') + ".class";
    try (InputStream in =
        Thread.currentThread().getContextClassLoader().getResourceAsStream(path)) {
      return new DexConverter(new Dexing(new DxContext(), new DexOptions(), new CfOptions()))
          .toDexFile(ByteStreams.toByteArray(in), path);
    }
  }
}
