/** * Copyright (c) 2016 Couchbase, Inc. 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.couchbase.lite; import com.couchbase.lite.storage.SQLiteJsonCollator; import com.couchbase.lite.storage.SQLiteRevCollator; import com.couchbase.lite.util.Log; import com.fasterxml.jackson.databind.ObjectMapper; import junit.framework.Assert; import java.text.Collator; import java.util.Locale; public class CollationTest extends LiteTestCaseWithDB { public static String TAG = "Collation"; private static final int kJsonCollator_Unicode = 0; private static final int kJsonCollator_Raw = 1; private static final int kJsonCollator_ASCII = 2; public void runBare() throws Throwable { // Run only for SQLite super.runBare(false); } // create the same JSON encoding used by TouchDB // this lets us test comparisons as they would be encoded public String encode(Object obj) { ObjectMapper mapper = new ObjectMapper(); try { byte[] bytes = mapper.writeValueAsBytes(obj); String result = new String(bytes); return result; } catch (Exception e) { Log.e(TAG, "Error encoding JSON", e); return null; } } public void testCollateScalars() { int mode = kJsonCollator_Unicode; Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "true", "false")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "false", "true")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "null", "17")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "1", "1")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "123", "1")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "123", "0123.0")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "123", "\"123\"")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "\"1234\"", "\"123\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"123\"", "\"1234\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"1234\"", "\"1235\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"1234\"", "\"1234\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"12\\/34\"", "\"12/34\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"\\/1234\"", "\"/1234\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"1234\\/\"", "\"1234/\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "123", "00000000000000000000000000000000000000000000000000123")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"a\"", "\"A\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"A\"", "\"aa\"")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "\"B\"", "\"aa\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"~\"", "\"A\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"_\"", "\"A\"")); } public void testCollateASCII() { int mode = kJsonCollator_ASCII; Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "true", "false")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "false", "true")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "null", "17")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "123", "1")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "123", "0123.0")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "123", "\"123\"")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "\"1234\"", "\"123\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"1234\"", "\"1235\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"1234\"", "\"1234\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"12\\/34\"", "\"12/34\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"\\/1234\"", "\"/1234\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "\"1234\\/\"", "\"1234/\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"A\"", "\"a\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"B\"", "\"a\"")); } public void testCollateRaw() { int mode = kJsonCollator_Raw; Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "false", "17")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "false", "true")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "null", "true")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "[\"A\"]", "\"A\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "\"A\"", "\"a\"")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "[\"b\"]", "[\"b\",\"c\",\"a\"]")); } public void testCollateArrays() { int mode = kJsonCollator_Unicode; Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "[]", "\"foo\"")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "[]", "[]")); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, "[true]", "[true]")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "[false]", "[null]")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "[]", "[null]")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "[123]", "[45]")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "[123]", "[45,67]")); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "[123.4,\"wow\"]", "[123.40,789]")); } public void testCollateNestedArray() { int mode = kJsonCollator_Unicode; Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, "[[]]", "[]")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, "[1,[2,3],4]", "[1,[2,3.1],4,5,6]")); } public void testCollateJapaneseStrings() { int mode = kJsonCollator_Unicode; // en_US Collator c = Collator.getInstance(new Locale("en_US")); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, encode("あ"), encode("い"))); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, encode("い"), encode("あ"))); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, encode("あ"), encode("あ"))); Assert.assertEquals(c.compare("カー", "カア"), SQLiteJsonCollator.testCollate(mode, encode("カー"), encode("カア"))); Assert.assertEquals(c.compare("鞍", "倉"), SQLiteJsonCollator.testCollate(mode, encode("鞍"), encode("倉"))); Assert.assertEquals(c.compare("鞍", "蔵"), SQLiteJsonCollator.testCollate(mode, encode("鞍"), encode("蔵"))); Assert.assertEquals(c.compare("倉", "蔵"), SQLiteJsonCollator.testCollate(mode, encode("倉"), encode("蔵"))); Assert.assertEquals(c.compare("倉", "鞍"), SQLiteJsonCollator.testCollate(mode, encode("倉"), encode("鞍"))); Assert.assertEquals(c.compare("蔵", "鞍"), SQLiteJsonCollator.testCollate(mode, encode("蔵"), encode("鞍"))); Assert.assertEquals(c.compare("蔵", "倉"), SQLiteJsonCollator.testCollate(mode, encode("蔵"), encode("倉"))); // ja Locale locale = new Locale("ja"); String localeStr = locale.toString(); Collator c1 = Collator.getInstance(locale); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, localeStr, encode("あ"), encode("い"))); Assert.assertEquals(1, SQLiteJsonCollator.testCollate(mode, localeStr, encode("い"), encode("あ"))); Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, localeStr, encode("あ"), encode("あ"))); Assert.assertEquals(c1.compare("カー", "カア"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("カー"), encode("カア"))); Assert.assertEquals(c1.compare("鞍", "倉"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("鞍"), encode("倉"))); Assert.assertEquals(c1.compare("鞍", "蔵"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("鞍"), encode("蔵"))); Assert.assertEquals(c1.compare("倉", "蔵"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("倉"), encode("蔵"))); Assert.assertEquals(c1.compare("倉", "鞍"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("倉"), encode("鞍"))); Assert.assertEquals(c1.compare("蔵", "鞍"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("蔵"), encode("鞍"))); Assert.assertEquals(c1.compare("蔵", "倉"), SQLiteJsonCollator.testCollate(mode, localeStr, encode("蔵"), encode("倉"))); } public void testCollateUnicodeStrings() { int mode = kJsonCollator_Unicode; Assert.assertEquals(0, SQLiteJsonCollator.testCollate(mode, encode("fr�d"), encode("fr�d"))); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, encode("\t"), encode(" "))); Assert.assertEquals(-1, SQLiteJsonCollator.testCollate(mode, encode("\001"), encode(" "))); } public void testConvertEscape() { Assert.assertEquals('\\', SQLiteJsonCollator.testEscape("\\\\")); Assert.assertEquals('\t', SQLiteJsonCollator.testEscape("\\t")); Assert.assertEquals('E', SQLiteJsonCollator.testEscape("\\u0045")); Assert.assertEquals(1, SQLiteJsonCollator.testEscape("\\u0001")); Assert.assertEquals(0, SQLiteJsonCollator.testEscape("\\u0000")); } public void testDigitToInt() { Assert.assertEquals(1, SQLiteJsonCollator.testDigitToInt('1')); Assert.assertEquals(7, SQLiteJsonCollator.testDigitToInt('7')); Assert.assertEquals(0xc, SQLiteJsonCollator.testDigitToInt('c')); Assert.assertEquals(0xc, SQLiteJsonCollator.testDigitToInt('C')); } public void testCollateRevIds() { Assert.assertEquals(SQLiteRevCollator.testCollate("1-foo", "1-foo"), 0); Assert.assertEquals(SQLiteRevCollator.testCollate("2-bar", "1-foo"), 1); Assert.assertEquals(SQLiteRevCollator.testCollate("1-foo", "2-bar"), -1); // Multi-digit: Assert.assertEquals(SQLiteRevCollator.testCollate("123-bar", "456-foo"), -1); Assert.assertEquals(SQLiteRevCollator.testCollate("456-foo", "123-bar"), 1); Assert.assertEquals(SQLiteRevCollator.testCollate("456-foo", "456-foo"), 0); Assert.assertEquals(SQLiteRevCollator.testCollate("456-foo", "456-foofoo"), -1); // Different numbers of digits: Assert.assertEquals(SQLiteRevCollator.testCollate("89-foo", "123-bar"), -1); Assert.assertEquals(SQLiteRevCollator.testCollate("123-bar", "89-foo"), 1); // Edge cases: Assert.assertEquals(SQLiteRevCollator.testCollate("123-", "89-"), 1); Assert.assertEquals(SQLiteRevCollator.testCollate("123-a", "123-a"), 0); // Invalid rev IDs: Assert.assertEquals(SQLiteRevCollator.testCollate("-a", "-b"), -1); Assert.assertEquals(SQLiteRevCollator.testCollate("-", "-"), 0); Assert.assertEquals(SQLiteRevCollator.testCollate("", ""), 0); Assert.assertEquals(SQLiteRevCollator.testCollate("", "-b"), -1); Assert.assertEquals(SQLiteRevCollator.testCollate("bogus", "yo"), -1); Assert.assertEquals(SQLiteRevCollator.testCollate("bogus-x", "yo-y"), -1); } }