// Copyright 2010 Google Inc.
//
// 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.gwtorm.nosql;

import junit.framework.TestCase;

public class IndexKeyBuilderTest extends TestCase {
  public void testInt() {
    IndexKeyBuilder ib;

    ib = new IndexKeyBuilder();
    ib.add(0);
    assertEquals(new byte[] {0x00}, ib);

    ib = new IndexKeyBuilder();
    ib.add(1);
    assertEquals(new byte[] {0x01, 0x01}, ib);

    ib = new IndexKeyBuilder();
    ib.add(256);
    assertEquals(new byte[] {0x02, 0x01, 0x00}, ib);
  }

  public void testDelimiter() {
    IndexKeyBuilder ib = new IndexKeyBuilder();
    ib.delimiter();
    assertEquals(new byte[] {0x00, 0x01}, ib);
  }

  public void testStringASCII() {
    IndexKeyBuilder ib = new IndexKeyBuilder();
    ib.add("hi");
    assertEquals(new byte[] {'h', 'i'}, ib);
  }

  public void testStringNUL() {
    IndexKeyBuilder ib = new IndexKeyBuilder();
    ib.add("\0");
    assertEquals(new byte[] {0x00, (byte) 0xff}, ib);
  }

  public void testStringFF() {
    IndexKeyBuilder ib = new IndexKeyBuilder();
    ib.add(new byte[] {(byte) 0xff});
    assertEquals(new byte[] {(byte) 0xff, 0x00}, ib);
  }

  public void testInfinity() {
    IndexKeyBuilder ib = new IndexKeyBuilder();
    ib.infinity();
    assertEquals(new byte[] {(byte) 0xff, (byte) 0xff}, ib);
  }

  private static void assertEquals(byte[] exp, IndexKeyBuilder ic) {
    assertEquals(toString(exp), toString(ic.toByteArray()));
  }

  private static String toString(byte[] bin) {
    StringBuilder dst = new StringBuilder(bin.length * 2);
    for (byte b : bin) {
      dst.append(hexchar[(b >>> 4) & 0x0f]);
      dst.append(hexchar[b & 0x0f]);
    }
    return dst.toString();
  }

  private static final char[] hexchar =
      {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', //
          'a', 'b', 'c', 'd', 'e', 'f'};
}
