/* Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on May 29, 2008 */ package com.bigdata.sparse; import java.text.Collator; import java.util.Properties; import junit.framework.TestCase2; import com.bigdata.btree.keys.CollatorEnum; import com.bigdata.btree.keys.DefaultKeyBuilderFactory; import com.bigdata.btree.keys.IKeyBuilder; import com.bigdata.btree.keys.KeyBuilder; import com.ibm.icu.text.CollationKey; /** * Test suite for round trip of keys as encoded by * {@link Schema#fromKey(com.bigdata.btree.keys.IKeyBuilder, Object)}, by * {@link AtomicRowWriteRead}, and as decoded by the {@link KeyDecoder}. * <p> * Note: Not all information can be fully decoded. In particular, the exact * schema name and the value of the primary key for Unicode {@link KeyType}s * can not be directly recovered from the key. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestKeyEncodeDecode extends TestCase2 { public TestKeyEncodeDecode() { } public TestKeyEncodeDecode(String name) { super(name); } /** * Test for primitive data types where we can round trip the primary key * value. * * FIXME tests for other primitives * * FIXME tests for Unicode * * FIXME tests for ASCII * * FIXME tests for Date * * FIXME All unit tests in this class should be for all collators (e.g., an * abstract base class). */ public void test_primitive_long() { final IKeyBuilder keyBuilder = KeyBuilder.newUnicodeInstance(); final Schema schema = new Schema("Employee", "Id", KeyType.Long); final Long primaryKey = 1L; final byte[] key = schema.getKey(keyBuilder, primaryKey, "Id", 12L); final KeyDecoder decoded = new KeyDecoder(key); assertEquals(schema.getPrimaryKeyType(), decoded.getPrimaryKeyType()); assertEquals("Id", decoded.getColumnName()); assertEquals(12L, decoded.getTimestamp()); } /** * Unit test verifies that we can correctly locate the start of the column * name and decode the key when using {@link CollatorEnum#ICU}. */ public void test_keyDecode_ICU() { final Properties props = new Properties(); props.put(KeyBuilder.Options.COLLATOR, CollatorEnum.ICU.toString()); final IKeyBuilder keyBuilder = new DefaultKeyBuilderFactory(props) .getKeyBuilder(); assertTrue(keyBuilder.isUnicodeSupported()); doKeyDecodeTest(keyBuilder); // final Schema schema = new Schema("Employee", "Id", KeyType.Unicode); // final String primaryKey = "1L"; // final String column = "Id"; // final long writeTime = 12L; // final byte[] key = schema.getKey(keyBuilder, primaryKey, column, // writeTime); // final KeyDecoder decoded = new KeyDecoder(key); // // assertEquals(schema.getPrimaryKeyType(), decoded.getPrimaryKeyType()); // assertEquals(column, decoded.getColumnName()); // assertEquals(writeTime, decoded.getTimestamp()); } /** * Unit test verifies that we can correctly locate the start of the column * name and decode the key when using {@link CollatorEnum#ASCII}. */ public void test_keyDecode_ASCII() { final Properties props = new Properties(); props.put(KeyBuilder.Options.COLLATOR,CollatorEnum.ASCII.toString()); final IKeyBuilder keyBuilder = new DefaultKeyBuilderFactory(props).getKeyBuilder(); assertFalse(keyBuilder.isUnicodeSupported()); doKeyDecodeTest(keyBuilder); } /** * Unit test verifies that we can correctly locate the start of the column * name and decode the key when using {@link CollatorEnum#JDK}. * <p> * Note: The JDK {@link CollationKey} embeds <code>nul</code> bytes in its * Unicode sort keys. */ public void test_keyDecode_JDK() { final Properties props = new Properties(); props.put(KeyBuilder.Options.COLLATOR,CollatorEnum.JDK.toString()); props.put(KeyBuilder.Options.USER_COUNTRY, "US"); props.put(KeyBuilder.Options.USER_LANGUAGE, "en"); props.put(KeyBuilder.Options.STRENGTH,Collator.TERTIARY); final IKeyBuilder keyBuilder = new DefaultKeyBuilderFactory(props).getKeyBuilder(); assertTrue(keyBuilder.isUnicodeSupported()); doKeyDecodeTest(keyBuilder); } /** * Test helper verifies that we can correctly locate the start of the column * name and decode the key when using a given {@link IKeyBuilder}. */ protected void doKeyDecodeTest(final IKeyBuilder keyBuilder) { final Schema schema = new MySchema(); final String primaryKey = "U100.lex"; final String column = "com.bigdata.btree.keys.KeyBuilder.collator"; final long writeTime = 1279133923566L; final byte[] key = schema.getKey(keyBuilder, primaryKey, column, writeTime); final KeyDecoder decoded = new KeyDecoder(key); System.err.println("decoded: "+decoded); if(SparseRowStore.schemaNameUnicodeClean) { assertEquals(schema.getName(),decoded.getSchemaName()); } assertEquals(schema.getPrimaryKeyType(), decoded.getPrimaryKeyType()); if(SparseRowStore.primaryKeyUnicodeClean) { assertEquals(primaryKey,decoded.getPrimaryKey()); } /* * Note: Historically, this would fail on the column name for the JDK * CollatorEnum option. The problem was that the JDK CollatorEnum option * embeds nul bytes into the primaryKey so we are not able to correctly * locate the start of the column name. This was resolved with the * [primaryKeyUnicodeClean] option. */ assertEquals(column, decoded.getColumnName()); assertEquals(writeTime, decoded.getTimestamp()); } /** * Private schema used by the unit tests. */ static private class MySchema extends Schema { /** * The primary key. */ public static final String NAMESPACE = MySchema.class.getPackage() .getName() + ".namespace"; public MySchema() { super("my/own-schema_now.10.0", NAMESPACE, KeyType.Unicode); } } }