/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to you 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 org.eigenbase.util; import java.io.*; import java.lang.management.*; import java.math.*; import java.sql.Timestamp; import java.text.MessageFormat; import java.util.*; import javax.annotation.Nullable; import org.eigenbase.resource.Resources; import org.eigenbase.sql.*; import org.eigenbase.sql.util.*; import org.eigenbase.test.*; import net.hydromatic.linq4j.function.Function1; import net.hydromatic.optiq.runtime.FlatLists; import net.hydromatic.optiq.runtime.Spaces; import net.hydromatic.optiq.util.BitSets; import net.hydromatic.optiq.util.Compatible; import net.hydromatic.optiq.util.CompositeMap; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.junit.BeforeClass; import org.junit.Test; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; /** * Unit test for {@link Util} and other classes in this package. */ public class UtilTest { //~ Constructors ----------------------------------------------------------- public UtilTest() { } //~ Methods ---------------------------------------------------------------- @BeforeClass public static void setUSLocale() { // This ensures numbers in exceptions are printed as in asserts. // For example, 1,000 vs 1 000 Locale.setDefault(Locale.US); } @Test public void testPrintEquals() { assertPrintEquals("\"x\"", "x", true); } @Test public void testPrintEquals2() { assertPrintEquals("\"x\"", "x", false); } @Test public void testPrintEquals3() { assertPrintEquals("null", null, true); } @Test public void testPrintEquals4() { assertPrintEquals("", null, false); } @Test public void testPrintEquals5() { assertPrintEquals("\"\\\\\\\"\\r\\n\"", "\\\"\r\n", true); } @Test public void testScientificNotation() { BigDecimal bd; bd = new BigDecimal("0.001234"); TestUtil.assertEqualsVerbose( "1.234E-3", Util.toScientificNotation(bd)); bd = new BigDecimal("0.001"); TestUtil.assertEqualsVerbose( "1E-3", Util.toScientificNotation(bd)); bd = new BigDecimal("-0.001"); TestUtil.assertEqualsVerbose( "-1E-3", Util.toScientificNotation(bd)); bd = new BigDecimal("1"); TestUtil.assertEqualsVerbose( "1E0", Util.toScientificNotation(bd)); bd = new BigDecimal("-1"); TestUtil.assertEqualsVerbose( "-1E0", Util.toScientificNotation(bd)); bd = new BigDecimal("1.0"); TestUtil.assertEqualsVerbose( "1.0E0", Util.toScientificNotation(bd)); bd = new BigDecimal("12345"); TestUtil.assertEqualsVerbose( "1.2345E4", Util.toScientificNotation(bd)); bd = new BigDecimal("12345.00"); TestUtil.assertEqualsVerbose( "1.234500E4", Util.toScientificNotation(bd)); bd = new BigDecimal("12345.001"); TestUtil.assertEqualsVerbose( "1.2345001E4", Util.toScientificNotation(bd)); // test truncate bd = new BigDecimal("1.23456789012345678901"); TestUtil.assertEqualsVerbose( "1.2345678901234567890E0", Util.toScientificNotation(bd)); bd = new BigDecimal("-1.23456789012345678901"); TestUtil.assertEqualsVerbose( "-1.2345678901234567890E0", Util.toScientificNotation(bd)); } @Test public void testToJavaId() throws UnsupportedEncodingException { assertEquals( "ID$0$foo", Util.toJavaId("foo", 0)); assertEquals( "ID$0$foo_20_bar", Util.toJavaId("foo bar", 0)); assertEquals( "ID$0$foo__bar", Util.toJavaId("foo_bar", 0)); assertEquals( "ID$100$_30_bar", Util.toJavaId("0bar", 100)); assertEquals( "ID$0$foo0bar", Util.toJavaId("foo0bar", 0)); assertEquals( "ID$0$it_27_s_20_a_20_bird_2c__20_it_27_s_20_a_20_plane_21_", Util.toJavaId("it's a bird, it's a plane!", 0)); // Try some funny non-ASCII charsets assertEquals( "ID$0$_f6__cb__c4__ca__ae__c1__f9__cb_", Util.toJavaId( "\u00f6\u00cb\u00c4\u00ca\u00ae\u00c1\u00f9\u00cb", 0)); assertEquals( "ID$0$_f6cb__c4ca__aec1__f9cb_", Util.toJavaId("\uf6cb\uc4ca\uaec1\uf9cb", 0)); byte[] bytes1 = {3, 12, 54, 23, 33, 23, 45, 21, 127, -34, -92, -113}; assertEquals( "ID$0$_3__c_6_17__21__17__2d__15__7f__6cd9__fffd_", Util.toJavaId( new String(bytes1, "EUC-JP"), 0)); byte[] bytes2 = { 64, 32, 43, -45, -23, 0, 43, 54, 119, -32, -56, -34 }; assertEquals( "ID$0$_30c__3617__2117__2d15__7fde__a48f_", Util.toJavaId( new String(bytes1, "UTF-16"), 0)); } private void assertPrintEquals( String expect, String in, boolean nullMeansNull) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); Util.printJavaString(pw, in, nullMeansNull); pw.flush(); String out = sw.toString(); assertEquals(expect, out); } /** * Unit-test for {@link BitString}. */ @Test public void testBitString() { // Powers of two, minimal length. final BitString b0 = new BitString("", 0); final BitString b1 = new BitString("1", 1); final BitString b2 = new BitString("10", 2); final BitString b4 = new BitString("100", 3); final BitString b8 = new BitString("1000", 4); final BitString b16 = new BitString("10000", 5); final BitString b32 = new BitString("100000", 6); final BitString b64 = new BitString("1000000", 7); final BitString b128 = new BitString("10000000", 8); final BitString b256 = new BitString("100000000", 9); // other strings final BitString b0x1 = new BitString("", 1); final BitString b0x12 = new BitString("", 12); // conversion to hex strings assertEquals( "", b0.toHexString()); assertEquals( "1", b1.toHexString()); assertEquals( "2", b2.toHexString()); assertEquals( "4", b4.toHexString()); assertEquals( "8", b8.toHexString()); assertEquals( "10", b16.toHexString()); assertEquals( "20", b32.toHexString()); assertEquals( "40", b64.toHexString()); assertEquals( "80", b128.toHexString()); assertEquals( "100", b256.toHexString()); assertEquals( "0", b0x1.toHexString()); assertEquals( "000", b0x12.toHexString()); // to byte array assertByteArray("01", "1", 1); assertByteArray("01", "1", 5); assertByteArray("01", "1", 8); assertByteArray("00, 01", "1", 9); assertByteArray("", "", 0); assertByteArray("00", "0", 1); assertByteArray("00", "0000", 2); // bit count less than string assertByteArray("00", "000", 5); // bit count larger than string assertByteArray("00", "0", 8); // precisely 1 byte assertByteArray("00, 00", "00", 9); // just over 1 byte // from hex string assertReversible(""); assertReversible("1"); assertReversible("10"); assertReversible("100"); assertReversible("1000"); assertReversible("10000"); assertReversible("100000"); assertReversible("1000000"); assertReversible("10000000"); assertReversible("100000000"); assertReversible("01"); assertReversible("001010"); assertReversible("000000000100"); } private static void assertReversible(String s) { assertEquals( s, BitString.createFromBitString(s).toBitString(), s); assertEquals( s, BitString.createFromHexString(s).toHexString()); } private void assertByteArray( String expected, String bits, int bitCount) { byte[] bytes = BitString.toByteArrayFromBitString(bits, bitCount); final String s = toString(bytes); assertEquals(expected, s); } /** * Converts a byte array to a hex string like "AB, CD". */ private String toString(byte[] bytes) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; if (i > 0) { buf.append(", "); } String s = Integer.toString(b, 16); buf.append((b < 16) ? ("0" + s) : s); } return buf.toString(); } /** * Tests {@link CastingList} and {@link Util#cast}. */ @Test public void testCastingList() { final List<Number> numberList = new ArrayList<Number>(); numberList.add(new Integer(1)); numberList.add(null); numberList.add(new Integer(2)); List<Integer> integerList = Util.cast(numberList, Integer.class); assertEquals(3, integerList.size()); assertEquals(new Integer(2), integerList.get(2)); // Nulls are OK. assertNull(integerList.get(1)); // Can update the underlying list. integerList.set(1, 345); assertEquals(new Integer(345), integerList.get(1)); integerList.set(1, null); assertNull(integerList.get(1)); // Can add a member of the wrong type to the underlying list. numberList.add(new Double(3.1415)); assertEquals(4, integerList.size()); // Access a member which is of the wrong type. try { integerList.get(3); fail("expected exception"); } catch (ClassCastException e) { // ok } } @Test public void testIterableProperties() { Properties properties = new Properties(); properties.put("foo", "george"); properties.put("bar", "ringo"); StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : Util.toMap(properties).entrySet()) { sb.append(entry.getKey()).append("=").append(entry.getValue()); sb.append(";"); } assertEquals("bar=ringo;foo=george;", sb.toString()); assertEquals(2, Util.toMap(properties).entrySet().size()); properties.put("nonString", 34); try { for (Map.Entry<String, String> e : Util.toMap(properties).entrySet()) { String s = e.getValue(); Util.discard(s); } fail("expected exception"); } catch (ClassCastException e) { // ok } } /** * Tests the difference engine, {@link DiffTestCase#diff}. */ @Test public void testDiffLines() { String[] before = { "Get a dose of her in jackboots and kilt", "She's killer-diller when she's dressed to the hilt", "She's the kind of a girl that makes The News of The World", "Yes you could say she was attractively built.", "Yeah yeah yeah." }; String[] after = { "Get a dose of her in jackboots and kilt", "(they call her \"Polythene Pam\")", "She's killer-diller when she's dressed to the hilt", "She's the kind of a girl that makes The Sunday Times", "seem more interesting.", "Yes you could say she was attractively built." }; String diff = DiffTestCase.diffLines( Arrays.asList(before), Arrays.asList(after)); assertThat(Util.toLinux(diff), equalTo( "1a2\n" + "> (they call her \"Polythene Pam\")\n" + "3c4,5\n" + "< She's the kind of a girl that makes The News of The World\n" + "---\n" + "> She's the kind of a girl that makes The Sunday Times\n" + "> seem more interesting.\n" + "5d6\n" + "< Yeah yeah yeah.\n")); } /** * Tests the {@link Util#toPosix(TimeZone, boolean)} method. */ @Test public void testPosixTimeZone() { // NOTE jvs 31-July-2007: First two tests are disabled since // not everyone may have patched their system yet for recent // DST change. // Pacific Standard Time. Effective 2007, the local time changes from // PST to PDT at 02:00 LST to 03:00 LDT on the second Sunday in March // and returns at 02:00 LDT to 01:00 LST on the first Sunday in // November. if (false) { assertEquals( "PST-8PDT,M3.2.0,M11.1.0", Util.toPosix(TimeZone.getTimeZone("PST"), false)); assertEquals( "PST-8PDT1,M3.2.0/2,M11.1.0/2", Util.toPosix(TimeZone.getTimeZone("PST"), true)); } // Tokyo has +ve offset, no DST assertEquals( "JST9", Util.toPosix(TimeZone.getTimeZone("Asia/Tokyo"), true)); // Sydney, Australia lies ten hours east of GMT and makes a one hour // shift forward during daylight savings. Being located in the southern // hemisphere, daylight savings begins on the last Sunday in October at // 2am and ends on the last Sunday in March at 3am. // (Uses STANDARD_TIME time-transition mode.) // Because australia changed their daylight savings rules, some JVMs // have a different (older and incorrect) timezone settings for // Australia. So we test for the older one first then do the // correct assert based upon what the toPosix method returns String posixTime = Util.toPosix(TimeZone.getTimeZone("Australia/Sydney"), true); if (posixTime.equals("EST10EST1,M10.5.0/2,M3.5.0/3")) { // older JVMs without the fix assertEquals("EST10EST1,M10.5.0/2,M3.5.0/3", posixTime); } else { // newer JVMs with the fix assertEquals("EST10EST1,M10.1.0/2,M4.1.0/3", posixTime); } // Paris, France. (Uses UTC_TIME time-transition mode.) assertEquals( "CET1CEST1,M3.5.0/2,M10.5.0/3", Util.toPosix(TimeZone.getTimeZone("Europe/Paris"), true)); assertEquals( "UTC0", Util.toPosix(TimeZone.getTimeZone("UTC"), true)); } /** * Tests the methods {@link Util#enumConstants(Class)} and {@link * Util#enumVal(Class, String)}. */ @Test public void testEnumConstants() { final Map<String, MemoryType> memoryTypeMap = Util.enumConstants(MemoryType.class); assertEquals(2, memoryTypeMap.size()); assertEquals(MemoryType.HEAP, memoryTypeMap.get("HEAP")); assertEquals(MemoryType.NON_HEAP, memoryTypeMap.get("NON_HEAP")); try { memoryTypeMap.put("FOO", null); fail("expected exception"); } catch (UnsupportedOperationException e) { // expected: map is immutable } assertEquals("HEAP", Util.enumVal(MemoryType.class, "HEAP").name()); assertNull(Util.enumVal(MemoryType.class, "heap")); assertNull(Util.enumVal(MemoryType.class, "nonexistent")); } /** * Tests SQL builders. */ @Test public void testSqlBuilder() { final SqlBuilder buf = new SqlBuilder(SqlDialect.EIGENBASE); assertEquals(0, buf.length()); buf.append("select "); assertEquals("select ", buf.getSql()); buf.identifier("x"); assertEquals("select \"x\"", buf.getSql()); buf.append(", "); buf.identifier("y", "a b"); assertEquals("select \"x\", \"y\".\"a b\"", buf.getSql()); final SqlString sqlString = buf.toSqlString(); assertEquals(SqlDialect.EIGENBASE, sqlString.getDialect()); assertEquals(buf.getSql(), sqlString.getSql()); assertTrue(buf.getSql().length() > 0); assertEquals(buf.getSqlAndClear(), sqlString.getSql()); assertEquals(0, buf.length()); buf.clear(); assertEquals(0, buf.length()); buf.literal("can't get no satisfaction"); assertEquals("'can''t get no satisfaction'", buf.getSqlAndClear()); buf.literal(new Timestamp(0)); assertEquals("TIMESTAMP '1970-01-01 00:00:00'", buf.getSqlAndClear()); buf.clear(); assertEquals(0, buf.length()); buf.append("hello world"); assertEquals(2, buf.indexOf("l")); assertEquals(-1, buf.indexOf("z")); assertEquals(9, buf.indexOf("l", 5)); } /** * Unit test for {@link org.eigenbase.util.CompositeList}. */ @Test public void testCompositeList() { // Made up of zero lists //noinspection unchecked List<String> list = CompositeList.of(new List[0]); assertEquals(0, list.size()); assertTrue(list.isEmpty()); try { final String s = list.get(0); fail("expected error, got " + s); } catch (IndexOutOfBoundsException e) { // ok } assertFalse(list.listIterator().hasNext()); List<String> listEmpty = Collections.emptyList(); List<String> listAbc = Arrays.asList("a", "b", "c"); List<String> listEmpty2 = new ArrayList<String>(); // Made up of three lists, two of which are empty list = CompositeList.of(listEmpty, listAbc, listEmpty2); assertEquals(3, list.size()); assertFalse(list.isEmpty()); assertEquals("a", list.get(0)); assertEquals("c", list.get(2)); try { final String s = list.get(3); fail("expected error, got " + s); } catch (IndexOutOfBoundsException e) { // ok } try { final String s = list.set(0, "z"); fail("expected error, got " + s); } catch (UnsupportedOperationException e) { // ok } // Iterator final Iterator<String> iterator = list.iterator(); assertTrue(iterator.hasNext()); assertEquals("a", iterator.next()); assertEquals("b", iterator.next()); assertTrue(iterator.hasNext()); try { iterator.remove(); fail("expected error"); } catch (UnsupportedOperationException e) { // ok } assertEquals("c", iterator.next()); assertFalse(iterator.hasNext()); // Extend one of the backing lists, and list grows. listEmpty2.add("zz"); assertEquals(4, list.size()); assertEquals("zz", list.get(3)); // Syntactic sugar 'of' method String ss = ""; for (String s : CompositeList.of(list, list)) { ss += s; } assertEquals("abczzabczz", ss); } /** * Unit test for {@link Template}. */ @Test public void testTemplate() { // Regular java message format. assertEquals( "Hello, world, what a nice day.", MessageFormat.format( "Hello, {0}, what a nice {1}.", "world", "day")); // Our extended message format. First, just strings. final HashMap<Object, Object> map = new HashMap<Object, Object>(); map.put("person", "world"); map.put("time", "day"); assertEquals( "Hello, world, what a nice day.", Template.formatByName( "Hello, {person}, what a nice {time}.", map)); // String and an integer. final Template template = Template.of("Happy {age,number,#.00}th birthday, {person}!"); map.clear(); map.put("person", "Ringo"); map.put("age", 64.5); assertEquals( "Happy 64.50th birthday, Ringo!", template.format(map)); // Missing parameters evaluate to null. map.remove("person"); assertEquals( "Happy 64.50th birthday, null!", template.format(map)); // Specify parameter by Integer ordinal. map.clear(); map.put(1, "Ringo"); map.put("0", 64.5); assertEquals( "Happy 64.50th birthday, Ringo!", template.format(map)); // Too many parameters supplied. map.put("lastName", "Starr"); map.put("homeTown", "Liverpool"); assertEquals( "Happy 64.50th birthday, Ringo!", template.format(map)); // Get parameter names. In order of appearance. assertEquals( Arrays.asList("age", "person"), template.getParameterNames()); // No parameters; doubled single quotes; quoted braces. final Template template2 = Template.of("Don''t expand 'this {brace}'."); assertEquals( Collections.<String>emptyList(), template2.getParameterNames()); assertEquals( "Don't expand this {brace}.", template2.format(Collections.<Object, Object>emptyMap())); // Empty template. assertEquals("", Template.formatByName("", map)); } /** * Unit test for {@link Util#parseLocale(String)} method. */ @Test public void testParseLocale() { Locale[] locales = { Locale.CANADA, Locale.CANADA_FRENCH, Locale.getDefault(), Locale.US, Locale.TRADITIONAL_CHINESE, }; for (Locale locale : locales) { assertEquals(locale, Util.parseLocale(locale.toString())); } // Example locale names in Locale.toString() javadoc. String[] localeNames = { "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC" }; for (String localeName : localeNames) { assertEquals(localeName, Util.parseLocale(localeName).toString()); } } @Test public void testSpaces() { assertEquals("", Spaces.of(0)); assertEquals(" ", Spaces.of(1)); assertEquals(" ", Spaces.of(1)); assertEquals(" ", Spaces.of(9)); assertEquals(" ", Spaces.of(5)); assertEquals(1000, Spaces.of(1000).length()); } @Test public void testSpaceString() { assertThat(Spaces.sequence(0).toString(), equalTo("")); assertThat(Spaces.sequence(1).toString(), equalTo(" ")); assertThat(Spaces.sequence(9).toString(), equalTo(" ")); assertThat(Spaces.sequence(5).toString(), equalTo(" ")); String s = new StringBuilder().append("xx").append(Spaces.MAX, 0, 100) .toString(); assertThat(s.length(), equalTo(102)); // this would blow memory if the string were materialized... check that it // is not assertThat(Spaces.sequence(1000000000).length(), equalTo(1000000000)); final StringWriter sw = new StringWriter(); Spaces.append(sw, 4); assertThat(sw.toString(), equalTo(" ")); final StringBuilder buf = new StringBuilder(); Spaces.append(buf, 4); assertThat(buf.toString(), equalTo(" ")); assertThat(Spaces.padLeft("xy", 5), equalTo(" xy")); assertThat(Spaces.padLeft("abcde", 5), equalTo("abcde")); assertThat(Spaces.padLeft("abcdef", 5), equalTo("abcdef")); assertThat(Spaces.padRight("xy", 5), equalTo("xy ")); assertThat(Spaces.padRight("abcde", 5), equalTo("abcde")); assertThat(Spaces.padRight("abcdef", 5), equalTo("abcdef")); } /** * Unit test for {@link Pair#zip(java.util.List, java.util.List)}. */ @Test public void testPairZip() { List<String> strings = Arrays.asList("paul", "george", "john", "ringo"); List<Integer> integers = Arrays.asList(1942, 1943, 1940); List<Pair<String, Integer>> zip = Pair.zip(strings, integers); assertEquals(3, zip.size()); assertEquals("paul:1942", zip.get(0).left + ":" + zip.get(0).right); assertEquals("john", zip.get(2).left); int x = 0; for (Pair<String, Integer> pair : zip) { x += pair.right; } assertEquals(5825, x); } /** * Unit test for {@link Pair#adjacents(Iterable)}. */ @Test public void testPairAdjacents() { List<String> strings = Arrays.asList("a", "b", "c"); List<String> result = new ArrayList<String>(); for (Pair<String, String> pair : Pair.adjacents(strings)) { result.add(pair.toString()); } assertThat(result.toString(), equalTo("[<a, b>, <b, c>]")); // empty source yields empty result assertThat(Pair.adjacents(ImmutableList.of()).iterator().hasNext(), is(false)); // source with 1 element yields empty result assertThat(Pair.adjacents(ImmutableList.of("a")).iterator().hasNext(), is(false)); // source with 100 elements yields result with 99 elements; // null elements are ok assertThat(Iterables.size(Pair.adjacents(Collections.nCopies(100, null))), equalTo(99)); } /** * Unit test for {@link Pair#firstAnd(Iterable)}. */ @Test public void testPairFirstAnd() { List<String> strings = Arrays.asList("a", "b", "c"); List<String> result = new ArrayList<String>(); for (Pair<String, String> pair : Pair.firstAnd(strings)) { result.add(pair.toString()); } assertThat(result.toString(), equalTo("[<a, b>, <a, c>]")); // empty source yields empty result assertThat(Pair.firstAnd(ImmutableList.of()).iterator().hasNext(), is(false)); // source with 1 element yields empty result assertThat(Pair.firstAnd(ImmutableList.of("a")).iterator().hasNext(), is(false)); // source with 100 elements yields result with 99 elements; // null elements are ok assertThat(Iterables.size(Pair.firstAnd(Collections.nCopies(100, null))), equalTo(99)); } /** * Unit test for {@link Util#quotientList(java.util.List, int, int)}. */ @Test public void testQuotientList() { List<String> beatles = Arrays.asList("john", "paul", "george", "ringo"); final List list0 = Util.quotientList(beatles, 3, 0); assertEquals(2, list0.size()); assertEquals("john", list0.get(0)); assertEquals("ringo", list0.get(1)); final List list1 = Util.quotientList(beatles, 3, 1); assertEquals(1, list1.size()); assertEquals("paul", list1.get(0)); final List list2 = Util.quotientList(beatles, 3, 2); assertEquals(1, list2.size()); assertEquals("george", list2.get(0)); try { final List listBad = Util.quotientList(beatles, 3, 4); fail("Expected error, got " + listBad); } catch (IllegalArgumentException e) { // ok } try { final List listBad = Util.quotientList(beatles, 3, 3); fail("Expected error, got " + listBad); } catch (IllegalArgumentException e) { // ok } try { final List listBad = Util.quotientList(beatles, 0, 0); fail("Expected error, got " + listBad); } catch (IllegalArgumentException e) { // ok } // empty final List<String> empty = Collections.emptyList(); final List<String> list3 = Util.quotientList(empty, 7, 2); assertEquals(0, list3.size()); // shorter than n final List list4 = Util.quotientList(beatles, 10, 0); assertEquals(1, list4.size()); assertEquals("john", list4.get(0)); final List list5 = Util.quotientList(beatles, 10, 5); assertEquals(0, list5.size()); } @Test public void testImmutableIntList() { ImmutableIntList list = ImmutableIntList.of(); assertEquals(0, list.size()); assertEquals(list, Collections.<Integer>emptyList()); assertThat(list.toString(), equalTo("[]")); assertThat(BitSets.of(list), equalTo(new BitSet())); list = ImmutableIntList.of(1, 3, 5); assertEquals(3, list.size()); assertEquals("[1, 3, 5]", list.toString()); assertEquals(list.hashCode(), Arrays.asList(1, 3, 5).hashCode()); Integer[] integers = list.toArray(new Integer[3]); assertEquals(1, (int) integers[0]); assertEquals(3, (int) integers[1]); assertEquals(5, (int) integers[2]); } /** * Unit test for {@link IntegerIntervalSet}. */ @Test public void testIntegerIntervalSet() { checkIntegerIntervalSet("1,5", 1, 5); // empty checkIntegerIntervalSet(""); // empty due to exclusions checkIntegerIntervalSet("2,4,-1-5"); // open range checkIntegerIntervalSet("1-6,-3-5,4,9", 1, 2, 4, 6, 9); // repeats checkIntegerIntervalSet("1,3,1,2-4,-2,-4", 1, 3); } private List<Integer> checkIntegerIntervalSet(String s, int... ints) { List<Integer> list = new ArrayList<Integer>(); final Set<Integer> set = IntegerIntervalSet.of(s); assertEquals(set.size(), ints.length); for (Integer integer : set) { list.add(integer); } assertEquals(new HashSet<Integer>(IntList.asList(ints)), set); return list; } /** * Tests that flat lists behave like regular lists in terms of equals * and hashCode. */ @Test public void testFlatList() { final List<String> emp = FlatLists.of(); final List<String> emp0 = Collections.emptyList(); assertEquals(emp, emp0); assertEquals(emp.hashCode(), emp0.hashCode()); final List<String> ab = FlatLists.of("A", "B"); final List<String> ab0 = Arrays.asList("A", "B"); assertEquals(ab, ab0); assertEquals(ab.hashCode(), ab0.hashCode()); final List<String> an = FlatLists.of("A", null); final List<String> an0 = Arrays.asList("A", null); assertEquals(an, an0); assertEquals(an.hashCode(), an0.hashCode()); final List<String> anb = FlatLists.of("A", null, "B"); final List<String> anb0 = Arrays.asList("A", null, "B"); assertEquals(anb, anb0); assertEquals(anb.hashCode(), anb0.hashCode()); } /** * Unit test for {@link Util#toCamelCase(String)}. */ @Test public void testToCamelCase() { assertEquals("myJdbcDriver", Util.toCamelCase("MY_JDBC_DRIVER")); assertEquals("myJdbcDriver", Util.toCamelCase("MY_JDBC__DRIVER")); assertEquals("myJdbcDriver", Util.toCamelCase("my_jdbc_driver")); assertEquals("abCdefGHij", Util.toCamelCase("ab_cdEf_g_Hij")); assertEquals("JdbcDriver", Util.toCamelCase("_JDBC_DRIVER")); assertEquals("", Util.toCamelCase("_")); assertEquals("", Util.toCamelCase("")); } /** * Unit test for {@link Util#camelToUpper(String)}. */ @Test public void testCamelToUpper() { assertEquals("MY_JDBC_DRIVER", Util.camelToUpper("myJdbcDriver")); assertEquals("MY_J_D_B_C_DRIVER", Util.camelToUpper("myJDBCDriver")); assertEquals("AB_CDEF_G_HIJ", Util.camelToUpper("abCdefGHij")); assertEquals("_JDBC_DRIVER", Util.camelToUpper("JdbcDriver")); assertEquals("", Util.camelToUpper("")); } /** * Unit test for {@link Util#isDistinct(java.util.List)}. */ @Test public void testDistinct() { assertTrue(Util.isDistinct(Collections.emptyList())); assertTrue(Util.isDistinct(Arrays.asList("a"))); assertTrue(Util.isDistinct(Arrays.asList("a", "b", "c"))); assertFalse(Util.isDistinct(Arrays.asList("a", "b", "a"))); assertTrue(Util.isDistinct(Arrays.asList("a", "b", null))); assertFalse(Util.isDistinct(Arrays.asList("a", null, "b", null))); } /** * Unit test for {@link org.eigenbase.util.JsonBuilder}. */ @Test public void testJsonBuilder() { JsonBuilder builder = new JsonBuilder(); Map<String, Object> map = builder.map(); map.put("foo", 1); map.put("baz", true); map.put("bar", "can't"); List<Object> list = builder.list(); map.put("list", list); list.add(2); list.add(3); list.add(builder.list()); list.add(builder.map()); list.add(null); map.put("nullValue", null); assertEquals( "{\n" + " foo: 1,\n" + " baz: true,\n" + " bar: \"can't\",\n" + " list: [\n" + " 2,\n" + " 3,\n" + " [],\n" + " {},\n" + " null\n" + " ],\n" + " nullValue: null\n" + "}", builder.toJsonString(map)); } @Test public void testCompositeMap() { String[] beatles = {"john", "paul", "george", "ringo"}; Map<String, Integer> beatleMap = new LinkedHashMap<String, Integer>(); for (String beatle : beatles) { beatleMap.put(beatle, beatle.length()); } CompositeMap<String, Integer> map = CompositeMap.of(beatleMap); checkCompositeMap(beatles, map); map = CompositeMap.of( beatleMap, Collections.<String, Integer>emptyMap()); checkCompositeMap(beatles, map); map = CompositeMap.of( Collections.<String, Integer>emptyMap(), beatleMap); checkCompositeMap(beatles, map); map = CompositeMap.of(beatleMap, beatleMap); checkCompositeMap(beatles, map); final Map<String, Integer> founderMap = new LinkedHashMap<String, Integer>(); founderMap.put("ben", 1706); founderMap.put("george", 1732); founderMap.put("thomas", 1743); map = CompositeMap.of(beatleMap, founderMap); assertThat(map.isEmpty(), equalTo(false)); assertThat(map.size(), equalTo(6)); assertThat(map.keySet().size(), equalTo(6)); assertThat(map.entrySet().size(), equalTo(6)); assertThat(map.values().size(), equalTo(6)); assertThat(map.containsKey("john"), equalTo(true)); assertThat(map.containsKey("george"), equalTo(true)); assertThat(map.containsKey("ben"), equalTo(true)); assertThat(map.containsKey("andrew"), equalTo(false)); assertThat(map.get("ben"), equalTo(1706)); assertThat(map.get("george"), equalTo(6)); // use value from first map assertThat(map.values().contains(1743), equalTo(true)); assertThat(map.values().contains(1732), equalTo(false)); // masked assertThat(map.values().contains(1999), equalTo(false)); } private void checkCompositeMap(String[] beatles, Map<String, Integer> map) { assertThat(4, equalTo(map.size())); assertThat(false, equalTo(map.isEmpty())); assertThat( map.keySet(), equalTo((Set<String>) new HashSet<String>(Arrays.asList(beatles)))); assertThat( ImmutableMultiset.copyOf(map.values()), equalTo(ImmutableMultiset.copyOf(Arrays.asList(4, 4, 6, 5)))); } /** Tests {@link Util#commaList(java.util.List)}. */ @Test public void testCommaList() { try { String s = Util.commaList(null); fail("expected NPE, got " + s); } catch (NullPointerException e) { // ok } assertThat(Util.commaList(ImmutableList.<Object>of()), equalTo("")); assertThat(Util.commaList(ImmutableList.of(1)), equalTo("1")); assertThat(Util.commaList(ImmutableList.of(2, 3)), equalTo("2, 3")); assertThat(Util.commaList(Arrays.asList(2, null, 3)), equalTo("2, null, 3")); } /** Unit test for {@link Util#firstDuplicate(java.util.List)}. */ @Test public void testFirstDuplicate() { assertThat(Util.firstDuplicate(ImmutableList.of()), equalTo(-1)); assertThat(Util.firstDuplicate(ImmutableList.of(5)), equalTo(-1)); assertThat(Util.firstDuplicate(ImmutableList.of(5, 6)), equalTo(-1)); assertThat(Util.firstDuplicate(ImmutableList.of(5, 6, 5)), equalTo(2)); assertThat(Util.firstDuplicate(ImmutableList.of(5, 5, 6)), equalTo(1)); assertThat(Util.firstDuplicate(ImmutableList.of(5, 5, 6, 5)), equalTo(1)); // list longer than 15, the threshold where we move to set-based algorithm assertThat( Util.firstDuplicate( ImmutableList.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 3, 19, 3, 21)), equalTo(18)); } /** Benchmark for {@link Util#isDistinct}. Has determined that map-based * implementation is better than nested loops implementation if list is larger * than about 15. */ @Test public void testIsDistinctBenchmark() { // Run a much quicker form of the test during regular testing. final int limit = Benchmark.enabled() ? 1000000 : 10; final int zMax = 100; for (int i = 0; i < 30; i++) { final int size = i; new Benchmark("isDistinct " + i + " (set)", new Function1<Benchmark.Statistician, Void>() { public Void apply(Benchmark.Statistician statistician) { final Random random = new Random(0); final List<List<Integer>> lists = new ArrayList<List<Integer>>(); for (int z = 0; z < zMax; z++) { final List<Integer> list = new ArrayList<Integer>(); for (int k = 0; k < size; k++) { list.add(random.nextInt(size * size)); } lists.add(list); } long nanos = System.nanoTime(); int n = 0; for (int j = 0; j < limit; j++) { n += Util.firstDuplicate(lists.get(j % zMax)); } statistician.record(nanos); Util.discard(n); return null; } }, 5).run(); } } /** Unit test for {@link Util#hashCode(double)}. */ @Test public void testHash() { checkHash(0d); checkHash(1d); checkHash(-2.5d); checkHash(10d / 3d); checkHash(Double.NEGATIVE_INFINITY); checkHash(Double.POSITIVE_INFINITY); checkHash(Double.MAX_VALUE); checkHash(Double.MIN_VALUE); } public void checkHash(double v) { assertThat(new Double(v).hashCode(), equalTo(Util.hashCode(v))); } /** Unit test for {@link Util#startsWith}. */ @Test public void testStartsWithList() { assertThat(Util.startsWith(list("x"), list()), is(true)); assertThat(Util.startsWith(list("x"), list("x")), is(true)); assertThat(Util.startsWith(list("x"), list("y")), is(false)); assertThat(Util.startsWith(list("x"), list("x", "y")), is(false)); assertThat(Util.startsWith(list("x", "y"), list("x")), is(true)); assertThat(Util.startsWith(list(), list()), is(true)); assertThat(Util.startsWith(list(), list("x")), is(false)); } public List<String> list(String... xs) { return Arrays.asList(xs); } @Test public void testResources() { Resources.validate(Static.RESOURCE); } /** Tests that sorted sets behave the way we expect. */ @Test public void testSortedSet() { final TreeSet<String> treeSet = new TreeSet<String>(); Collections.addAll(treeSet, "foo", "bar", "fOo", "FOO", "pug"); assertThat(treeSet.size(), equalTo(5)); final TreeSet<String> treeSet2 = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); treeSet2.addAll(treeSet); assertThat(treeSet2.size(), equalTo(3)); final Comparator<String> comparator = new Comparator<String>() { public int compare(String o1, String o2) { String u1 = o1.toUpperCase(); String u2 = o2.toUpperCase(); int c = u1.compareTo(u2); if (c == 0) { c = o1.compareTo(o2); } return c; } }; final TreeSet<String> treeSet3 = new TreeSet<String>(comparator); treeSet3.addAll(treeSet); assertThat(treeSet3.size(), equalTo(5)); assertThat(checkNav(treeSet3, "foo").size(), equalTo(3)); assertThat(checkNav(treeSet3, "FOO").size(), equalTo(3)); assertThat(checkNav(treeSet3, "FoO").size(), equalTo(3)); assertThat(checkNav(treeSet3, "BAR").size(), equalTo(1)); final ImmutableSortedSet<String> treeSet4 = ImmutableSortedSet.copyOf(comparator, treeSet); final NavigableSet<String> navigableSet4 = Compatible.INSTANCE.navigableSet(treeSet4); assertThat(treeSet4.size(), equalTo(5)); assertThat(navigableSet4.size(), equalTo(5)); assertThat(navigableSet4, equalTo((SortedSet<String>) treeSet4)); assertThat(checkNav(navigableSet4, "foo").size(), equalTo(3)); assertThat(checkNav(navigableSet4, "FOO").size(), equalTo(3)); assertThat(checkNav(navigableSet4, "FoO").size(), equalTo(3)); assertThat(checkNav(navigableSet4, "BAR").size(), equalTo(1)); } private NavigableSet<String> checkNav(NavigableSet<String> set, String s) { return set.subSet(s.toUpperCase(), true, s.toLowerCase(), true); } /** Test for {@link org.eigenbase.util.ImmutableNullableList}. */ @Test public void testImmutableNullableList() { final List<String> arrayList = Arrays.asList("a", null, "c"); final List<String> list = ImmutableNullableList.copyOf(arrayList); assertThat(list.size(), equalTo(arrayList.size())); assertThat(list, equalTo(arrayList)); assertThat(list.hashCode(), equalTo(arrayList.hashCode())); assertThat(list.toString(), equalTo(arrayList.toString())); String z = ""; for (String s : list) { z += s; } assertThat(z, equalTo("anullc")); // changes to array list do not affect copy arrayList.set(0, "z"); assertThat(arrayList.get(0), equalTo("z")); assertThat(list.get(0), equalTo("a")); try { boolean b = list.add("z"); fail("expected error, got " + b); } catch (UnsupportedOperationException e) { // ok } try { String b = list.set(1, "z"); fail("expected error, got " + b); } catch (UnsupportedOperationException e) { // ok } // empty list uses ImmutableList assertThat(ImmutableNullableList.copyOf(Collections.emptyList()), isA((Class) ImmutableList.class)); // list with no nulls uses ImmutableList assertThat(ImmutableNullableList.copyOf(Arrays.asList("a", "b", "c")), isA((Class) ImmutableList.class)); } /** Test for {@link org.eigenbase.util.UnmodifiableArrayList}. */ @Test public void testUnmodifiableArrayList() { final String[] strings = {"a", null, "c"}; final List<String> arrayList = Arrays.asList(strings); final List<String> list = UnmodifiableArrayList.of(strings); assertThat(list.size(), equalTo(arrayList.size())); assertThat(list, equalTo(arrayList)); assertThat(list.hashCode(), equalTo(arrayList.hashCode())); assertThat(list.toString(), equalTo(arrayList.toString())); String z = ""; for (String s : list) { z += s; } assertThat(z, equalTo("anullc")); // changes to array list do affect copy arrayList.set(0, "z"); assertThat(arrayList.get(0), equalTo("z")); assertThat(list.get(0), equalTo("z")); try { boolean b = list.add("z"); fail("expected error, got " + b); } catch (UnsupportedOperationException e) { // ok } try { String b = list.set(1, "z"); fail("expected error, got " + b); } catch (UnsupportedOperationException e) { // ok } } @Test public void testHuman() { assertThat(Util.human(0D), equalTo("0")); assertThat(Util.human(1D), equalTo("1")); assertThat(Util.human(19D), equalTo("19")); assertThat(Util.human(198D), equalTo("198")); assertThat(Util.human(1000D), equalTo("1.00K")); assertThat(Util.human(1002D), equalTo("1.00K")); assertThat(Util.human(1009D), equalTo("1.01K")); assertThat(Util.human(1234D), equalTo("1.23K")); assertThat(Util.human(1987D), equalTo("1.99K")); assertThat(Util.human(1999D), equalTo("2.00K")); assertThat(Util.human(86837.2D), equalTo("86.8K")); assertThat(Util.human(868372.8D), equalTo("868K")); assertThat(Util.human(1009000D), equalTo("1.01M")); assertThat(Util.human(1999999D), equalTo("2.00M")); assertThat(Util.human(1009000000D), equalTo("1.01G")); assertThat(Util.human(1999999000D), equalTo("2.00G")); assertThat(Util.human(-1D), equalTo("-1")); assertThat(Util.human(-19D), equalTo("-19")); assertThat(Util.human(-198D), equalTo("-198")); assertThat(Util.human(-1999999000D), equalTo("-2.00G")); // not ideal - should use m (milli) and u (micro) assertThat(Util.human(0.18D), equalTo("0.18")); assertThat(Util.human(0.018D), equalTo("0.018")); assertThat(Util.human(0.0018D), equalTo("0.0018")); assertThat(Util.human(0.00018D), equalTo("1.8E-4")); assertThat(Util.human(0.000018D), equalTo("1.8E-5")); assertThat(Util.human(0.0000018D), equalTo("1.8E-6")); // bad - should round to 3 digits assertThat(Util.human(0.181111D), equalTo("0.181111")); assertThat(Util.human(0.0181111D), equalTo("0.0181111")); assertThat(Util.human(0.00181111D), equalTo("0.00181111")); assertThat(Util.human(0.000181111D), equalTo("1.81111E-4")); assertThat(Util.human(0.0000181111D), equalTo("1.81111E-5")); assertThat(Util.human(0.00000181111D), equalTo("1.81111E-6")); } @Test public void testAsIndexView() { final List<String> values = Lists.newArrayList("abCde", "X", "y"); final Map<String, String> map = Util.asIndexMap(values, new Function<String, String>() { public String apply(@Nullable String input) { return input.toUpperCase(); } }); assertThat(map.size(), equalTo(values.size())); assertThat(map.get("X"), equalTo("X")); assertThat(map.get("Y"), equalTo("y")); assertThat(map.get("y"), is((String) null)); assertThat(map.get("ABCDE"), equalTo("abCde")); // If you change the values collection, the map changes. values.remove(1); assertThat(map.size(), equalTo(values.size())); assertThat(map.get("X"), is((String) null)); assertThat(map.get("Y"), equalTo("y")); } /** Unit test for {@link Util#isSorted(Iterable)}. */ @Test public void testIsSorted() { final List<String> empty = Collections.emptyList(); assertThat(Util.isSorted(empty), is(true)); final List<String> listA = Arrays.asList("a"); assertThat(Util.isSorted(listA), is(true)); final List<String> listAB = Arrays.asList("a", "b"); assertThat(Util.isSorted(listAB), is(true)); final List<String> listAA = Arrays.asList("a", "a"); assertThat(Util.isSorted(listAA), is(true)); final List<String> listABA = Arrays.asList("a", "b", "a"); assertThat(Util.isSorted(listABA), is(false)); } } // End UtilTest.java