// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.dex;

import static com.android.tools.r8.dex.Constants.DEX_MAGIC_SIZE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.EncodedValueUtils;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class EncodedFloatingValueTest {
  private final double value;

  public EncodedFloatingValueTest(double value) {
    this.value = value;
  }

  @Parameters(name = "{0}")
  public static Collection<Double> data() {
    return Arrays.asList(
        0.0,
        1.0,
        0.5,
        Double.longBitsToDouble(1), // Lowest bit is 1 in double
        Double.longBitsToDouble(0x10), // Bits on byte boundary are 1.
        Double.longBitsToDouble(0x08),
        Double.longBitsToDouble(4607071218809329336L),  // Test a real long (regression).
        (double) (Float.intBitsToFloat(1)), // Lowest bit is 1 in float
        (double) (Float.intBitsToFloat(0x10)), // Bits on byte boundary are 1
        (double) (Float.intBitsToFloat(0x08))
    );
  }

  // Create a DexFile with correct file magic followed by the argument bytes. Positions the
  // DexFile after the file magic.
  private DexFile createDexFileWithContent(byte[] bytes) {
    DexOutputBuffer buffer = new DexOutputBuffer();
    buffer.putBytes(Constants.DEX_FILE_MAGIC_PREFIX);
    buffer.putBytes(AndroidApiLevel.B.getDexVersion().getBytes());
    buffer.putByte(Constants.DEX_FILE_MAGIC_SUFFIX);
    buffer.putBytes(bytes);
    DexFile dexFile = new DexFile(Origin.unknown(), buffer.asArray());
    dexFile.position(DEX_MAGIC_SIZE);
    return dexFile;
  }

  @Test
  public void testEncodeDecodeDouble() {
    byte[] bytes = EncodedValueUtils.encodeDouble(value);
    assertTrue(bytes.length <= Double.BYTES);
    DexFile dexFile = createDexFileWithContent(bytes);
    Assert.assertEquals(value, EncodedValueUtils.parseDouble(dexFile, bytes.length), 0.0);
  }

  @Test
  public void testEncodeDecodeFloat() {
    byte[] bytes = EncodedValueUtils.encodeFloat((float) value);
    assertTrue(bytes.length <= Float.BYTES);
    DexFile dexFile = createDexFileWithContent(bytes);
    Assert.assertEquals((float) value, EncodedValueUtils.parseFloat(dexFile, bytes.length), 0.0f);
  }

  @Test
  public void testEncodeDecodeDoubleWithDexBuffer() {
    DexOutputBuffer buffer = new DexOutputBuffer();
    int length = EncodedValueUtils.putDouble(buffer, value);
    assertTrue(length <= Double.BYTES);
    byte[] bytes = buffer.asArray();
    DexFile dexFile = createDexFileWithContent(bytes);
    assertEquals(value, EncodedValueUtils.parseDouble(dexFile, length), 0.0);
  }

  @Test
  public void testEncodeDecodeFloatWithDexBuffer() {
    DexOutputBuffer buffer = new DexOutputBuffer();
    int length = EncodedValueUtils.putFloat(buffer, (float) value);
    assertTrue(length <= Float.BYTES);
    byte[] bytes = buffer.asArray();
    DexFile dexFile = createDexFileWithContent(bytes);
    assertEquals((float) value, EncodedValueUtils.parseFloat(dexFile, length), 0.0f);
  }
}
