// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf;

import static com.google.protobuf.IsValidUtf8TestUtil.DIRECT_NIO_FACTORY;
import static com.google.protobuf.IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT;
import static com.google.protobuf.IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT;
import static com.google.protobuf.IsValidUtf8TestUtil.HEAP_NIO_FACTORY;
import static com.google.protobuf.IsValidUtf8TestUtil.LITERAL_FACTORY;
import static com.google.protobuf.IsValidUtf8TestUtil.testBytes;

import com.google.protobuf.IsValidUtf8TestUtil.ByteStringFactory;
import com.google.protobuf.IsValidUtf8TestUtil.Shard;

import junit.framework.TestCase;

/**
 * Tests cases for {@link ByteString#isValidUtf8()}. This includes three
 * brute force tests that actually test every permutation of one byte, two byte,
 * and three byte sequences to ensure that the method produces the right result
 * for every possible byte encoding where "right" means it's consistent with
 * java's UTF-8 string encoding/decoding such that the method returns true for
 * any sequence that will round trip when converted to a String and then back to
 * bytes and will return false for any sequence that will not round trip.
 * See also {@link IsValidUtf8FourByteTest}. It also includes some
 * other more targeted tests.
 *
 * @author jonp@google.com (Jon Perlow)
 * @author martinrb@google.com (Martin Buchholz)
 */
public class IsValidUtf8Test extends TestCase {
  /**
   * Tests that round tripping of all two byte permutations work.
   */
  public void testIsValidUtf8_1Byte() {
    testBytes(LITERAL_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
    testBytes(HEAP_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
    testBytes(DIRECT_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
  }

  /**
   * Tests that round tripping of all two byte permutations work.
   */
  public void testIsValidUtf8_2Bytes() {
    testBytes(LITERAL_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
    testBytes(HEAP_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
    testBytes(DIRECT_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
  }

  /**
   * Tests that round tripping of all three byte permutations work.
   */
  public void testIsValidUtf8_3Bytes() {
    // Travis' OOM killer doesn't like this test
    if (System.getenv("TRAVIS") == null) {
      testBytes(LITERAL_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
      testBytes(HEAP_NIO_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
      testBytes(DIRECT_NIO_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
    }
  }

  /**
   * Tests that round tripping of a sample of four byte permutations work.
   * All permutations are prohibitively expensive to test for automated runs;
   * {@link IsValidUtf8FourByteTest} is used for full coverage. This method
   * tests specific four-byte cases.
   */
  public void testIsValidUtf8_4BytesSamples() {
    // Valid 4 byte.
    assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2);

    // Bad trailing bytes
    assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F);
    assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0);

    // Special cases for byte2
    assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2);
    assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2);
  }

  /**
   * Tests some hard-coded test cases.
   */
  public void testSomeSequences() {
    // Empty
    assertTrue(asBytes("").isValidUtf8());

    // One-byte characters, including control characters
    assertTrue(asBytes("\u0000abc\u007f").isValidUtf8());

    // Two-byte characters
    assertTrue(asBytes("\u00a2\u00a2").isValidUtf8());

    // Three-byte characters
    assertTrue(asBytes("\u020ac\u020ac").isValidUtf8());

    // Four-byte characters
    assertTrue(asBytes("\u024B62\u024B62").isValidUtf8());

    // Mixed string
    assertTrue(asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62").isValidUtf8());

    // Not a valid string
    assertInvalidUtf8(-1, 0, -1, 0);
  }

  private byte[] toByteArray(int... bytes) {
    byte[] realBytes = new byte[bytes.length];
    for (int i = 0; i < bytes.length; i++) {
      realBytes[i] = (byte) bytes[i];
    }
    return realBytes;
  }

  private void assertValidUtf8(ByteStringFactory factory, int[] bytes, boolean not) {
    byte[] realBytes = toByteArray(bytes);
    assertTrue(not ^ Utf8.isValidUtf8(realBytes));
    assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length));
    ByteString leaf = factory.newByteString(realBytes);
    ByteString sub = leaf.substring(0, bytes.length);
    assertTrue(not ^ leaf.isValidUtf8());
    assertTrue(not ^ sub.isValidUtf8());
    ByteString[] ropes = {
        RopeByteString.newInstanceForTest(ByteString.EMPTY, leaf),
        RopeByteString.newInstanceForTest(ByteString.EMPTY, sub),
        RopeByteString.newInstanceForTest(leaf, ByteString.EMPTY),
        RopeByteString.newInstanceForTest(sub, ByteString.EMPTY),
        RopeByteString.newInstanceForTest(sub, leaf)};
    for (ByteString rope : ropes) {
      assertTrue(not ^ rope.isValidUtf8());
    }
  }

  private void assertValidUtf8(int... bytes) {
    assertValidUtf8(LITERAL_FACTORY, bytes, false);
    assertValidUtf8(HEAP_NIO_FACTORY, bytes, false);
    assertValidUtf8(DIRECT_NIO_FACTORY, bytes, false);
  }

  private void assertInvalidUtf8(int... bytes) {
    assertValidUtf8(LITERAL_FACTORY, bytes, true);
    assertValidUtf8(HEAP_NIO_FACTORY, bytes, true);
    assertValidUtf8(DIRECT_NIO_FACTORY, bytes, true);
  }

  private static ByteString asBytes(String s) {
    return ByteString.copyFromUtf8(s);
  }

  public void testShardsHaveExpectedRoundTrippables() {
    // A sanity check.
    int actual = 0;
    for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
      actual += shard.expected;
    }
    assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
  }
}
