/*
* Copyright 2013-2015 the original author or authors.
*
* 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 org.springframework.xd.tuple;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.sameInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.springframework.xd.tuple.TupleBuilder.tuple;
import java.awt.Color;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.core.convert.ConverterNotFoundException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class DefaultTupleTests {
@Test(expected = IllegalArgumentException.class)
public void nullForNameArray() {
List<Object> values = new ArrayList<Object>();
values.add("bar");
tuple().ofNamesAndValues(null, values);
}
@Test(expected = IllegalArgumentException.class)
public void nullForValueArray() {
List<String> names = new ArrayList<String>();
names.add("foo");
tuple().ofNamesAndValues(names, null);
}
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void notEqualNumberOfNamesAndValues() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Field names must be same length as values: names=[foo, oof], values=[bar]");
List<String> names = new ArrayList<String>();
names.add("foo");
names.add("oof");
List<Object> values = new ArrayList<Object>();
values.add("bar");
tuple().ofNamesAndValues(names, values);
}
@Test
public void accessNonExistentEntry() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Field name [does-not-exist] does not exist");
Tuple tuple = TupleBuilder.tuple().of("foo", "bar");
Object v = tuple.getValue("does-not-exist");
assertThat(v, nullValue());
}
@Test
public void singleEntry() {
Tuple tuple = TupleBuilder.tuple().of("foo", "bar");
assertThat(tuple.size(), equalTo(1));
List<String> names = tuple.getFieldNames();
assertThat(names.get(0), equalTo("foo"));
assertThat((String) tuple.getValue("foo"), equalTo("bar"));
assertThat(tuple.hasFieldName("foo"), equalTo(true));
assertThat(tuple.getValue("foo").toString(), equalTo("bar"));
}
@Test
public void twoEntries() {
Tuple tuple = TupleBuilder.tuple().of("up", "down", "charm", "strange");
assertTwoEntries(tuple);
}
@Test
public void testTupleAsValue() {
Tuple t1 = tuple().of("up", 1, "down", 2);
Tuple t2 = tuple().of("1stgen", t1, "charm", 3, "strange", 4);
assertThat(t2.size(), equalTo(3));
Tuple t3 = t2.getTuple(0);
assertThat(t3.size(), equalTo(2));
assertThat(t3.getFieldNames().get(0), equalTo("up"));
assertThat(t3.getFieldNames().get(1), equalTo("down"));
assertThat(t3.getInt("up"), equalTo(1));
assertThat(t3.getInt("down"), equalTo(2));
Tuple t4 = t2.getTuple("1stgen");
assertThat(t3, equalTo(t4));
}
/**
* @param tuple
*/
private void assertTwoEntries(Tuple tuple) {
assertThat(tuple.size(), equalTo(2));
assertThat(tuple.getFieldNames().get(0), equalTo("up"));
assertThat(tuple.getFieldNames().get(1), equalTo("charm"));
assertThat((String) tuple.getValue("up"), equalTo("down"));
assertThat((String) tuple.getValue("charm"), equalTo("strange"));
}
@Test
public void threeEntries() {
Tuple tuple = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3);
assertThat(tuple.size(), equalTo(3));
assertThat(tuple.getFieldNames().get(0), equalTo("up"));
assertThat(tuple.getFieldNames().get(1), equalTo("charm"));
assertThat(tuple.getFieldNames().get(2), equalTo("top"));
// access by name
assertThat((Integer) tuple.getValue("up"), equalTo(1));
assertThat((Integer) tuple.getValue("charm"), equalTo(2));
assertThat((Integer) tuple.getValue("top"), equalTo(3));
// access by position
assertThat((Integer) tuple.getValue(0), equalTo(1));
assertThat((Integer) tuple.getValue(1), equalTo(2));
assertThat((Integer) tuple.getValue(2), equalTo(3));
// access from separate collection
List<Object> values = tuple.getValues();
assertThat((Integer) values.get(0), equalTo(1));
assertThat((Integer) values.get(1), equalTo(2));
assertThat((Integer) values.get(2), equalTo(3));
}
@Test
public void fourEntries() {
Tuple tuple = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3, "e", 4);
assertThat(tuple.size(), equalTo(4));
assertThat(tuple.getFieldNames().get(0), equalTo("up"));
assertThat(tuple.getFieldNames().get(1), equalTo("charm"));
assertThat(tuple.getFieldNames().get(2), equalTo("top"));
assertThat(tuple.getFieldNames().get(3), equalTo("e"));
// access by name
assertThat((Integer) tuple.getValue("up"), equalTo(1));
assertThat((Integer) tuple.getValue("charm"), equalTo(2));
assertThat((Integer) tuple.getValue("top"), equalTo(3));
assertThat((Integer) tuple.getValue("e"), equalTo(4));
// access by position
assertThat((Integer) tuple.getValue(0), equalTo(1));
assertThat((Integer) tuple.getValue(1), equalTo(2));
assertThat((Integer) tuple.getValue(2), equalTo(3));
assertThat((Integer) tuple.getValue(3), equalTo(4));
}
@Test
public void getValue() {
Tuple tuple = TupleBuilder.tuple().of("up", 1, "charm", 2.0, "top", true);
assertThat(tuple.getValue(0, Integer.class), equalTo(1));
assertThat(tuple.getValue(0, String.class), equalTo("1"));
assertThat(tuple.getValue(1, Double.class), equalTo(2.0D));
assertThat(tuple.getValue(2, Boolean.class), equalTo(true));
assertThat(tuple.getValue(2, String.class), equalTo("true"));
assertThat(tuple.getValue("up", Integer.class), equalTo(1));
assertThat(tuple.getValue("up", String.class), equalTo("1"));
assertThat(tuple.getValue("charm", Double.class), equalTo(2.0D));
assertThat(tuple.getValue("top", Boolean.class), equalTo(true));
assertThat(tuple.getValue("top", String.class), equalTo("true"));
}
@Test
public void testPrimitiveGetters() {
Tuple tuple = TupleBuilder.tuple().of("up", "down", "charm", 2.0, "top", true);
assertThat(tuple.getBoolean("top"), equalTo(true));
assertThat(tuple.getBoolean(2), equalTo(true));
assertThat(tuple.getBoolean("up", "down"), equalTo(true));
}
@Test
public void testToString() throws JsonProcessingException, IOException {
Tuple tuple = TupleBuilder.tuple().put("up", "down").put("charm", "strange").build();
String tupleString = tuple.toString();
// valid JSON
new ObjectMapper().readTree(tupleString);
Tuple tupleFromString = TupleBuilder.fromString(tupleString);
assertEquals(2, tupleFromString.getFieldCount());
assertEquals("down", tupleFromString.getString("up"));
assertEquals("strange", tupleFromString.getString("charm"));
}
@Test
public void testPutApi() {
TupleBuilder builder = TupleBuilder.tuple();
Tuple tuple = builder.put("up", "down").put("charm", "strange").build();
assertTwoEntries(tuple);
}
@Test
public void testPutAllApi() {
Tuple tuple = TupleBuilder.tuple().put("red", "rot").put("brown", "braun").put("blue", "blau").put("yellow",
"gelb").put("beige", "beige").build();
assertThat(tuple.size(), equalTo(5));
Tuple tuplePlusOne = TupleBuilder.tuple().putAll(tuple).put("up", 1).build();
assertThat(tuplePlusOne.size(), equalTo(6));
assertThat(tuplePlusOne.getFieldNames().get(0), equalTo("red"));
assertThat(tuplePlusOne.getFieldNames().get(5), equalTo("up"));
}
@Test
public void testEqualsAndHashCodeSunnyDay() {
Tuple tuple1 = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3);
Tuple tuple2 = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3);
assertThat(tuple1, equalTo(tuple2));
assertThat(tuple1.hashCode(), equalTo(tuple2.hashCode()));
assertThat(tuple1, not(sameInstance(tuple2)));
}
@Test
public void testEqualsAndHashFailureCases() {
Tuple tuple1 = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3);
Tuple tuple2 = TupleBuilder.tuple().of("up", 2, "charm", 3, "top", 4);
assertThat(tuple1, not(equalTo((tuple2))));
assertThat(tuple1.hashCode(), not(equalTo(tuple2.hashCode())));
tuple1 = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3);
tuple2 = TupleBuilder.tuple().of("top", 1, "charm", 2, "up", 3);
assertThat(tuple1, not(equalTo((tuple2))));
assertThat(tuple1.hashCode(), not(equalTo(tuple2.hashCode())));
}
@SuppressWarnings("rawtypes")
@Test
public void testGetFieldTypes() {
Tuple tuple = TupleBuilder.tuple().of("up", 1, "charm", 2, "top", 3);
Class[] expectedTypes = new Class[] { Integer.class, Integer.class, Integer.class };
assertThat(tuple.getFieldTypes(), equalTo(Arrays.asList(expectedTypes)));
tuple = TupleBuilder.tuple().of("up", 1, "charm", 2.0f, "top", "bottom");
expectedTypes = new Class[] { Integer.class, Float.class, String.class };
assertThat(tuple.getFieldTypes(), equalTo(Arrays.asList(expectedTypes)));
tuple = TupleBuilder.tuple().of("up", 1, "charm", 2.0, "top", true);
expectedTypes = new Class[] { Integer.class, Double.class, Boolean.class };
assertThat(tuple.getFieldTypes(), equalTo(Arrays.asList(expectedTypes)));
}
@Test
public void testGetString() {
// test conversions of string, int, and float.
Tuple tuple = TupleBuilder.tuple().of("up", "down", "charm", 2, "top", 2.0f);
assertThat(tuple.getString("up"), equalTo("down"));
assertThat(tuple.getString("charm"), equalTo("2"));
assertThat(tuple.getString("top"), equalTo("2.0"));
}
@Test
public void testGetNullValue() {
Tuple tuple = tuple().of("foo", null);
// non primitive types will return null
assertThat(tuple.getString("foo"), nullValue());
assertThat(tuple.getBigDecimal("foo"), nullValue());
assertThat(tuple.getDate("foo"), nullValue());
// primitive types will return default values
assertThat(tuple.getChar("foo"), equalTo('\u0000'));
assertThat(tuple.getBoolean("foo"), equalTo(false));
byte b = 0;
assertThat(tuple.getByte("foo"), equalTo(b));
short s = 0;
assertThat(tuple.getShort("foo"), equalTo(s));
assertThat(tuple.getInt("foo"), equalTo(0));
assertThat(tuple.getLong("foo"), equalTo(0L));
assertThat(tuple.getFloat("foo"), equalTo(0f));
assertThat(tuple.getDouble("foo"), equalTo(0d));
}
@Test
public void testGetStringThatFails() {
Tuple tuple = TupleBuilder.tuple().of("up", "down", "charm", 2, "top", 2.0f, "black", Color.black);
thrown.expect(ConverterNotFoundException.class);
thrown.expectMessage("No converter found capable of converting from type [java.awt.Color] to type "
+ "[java.lang.String]");
assertThat(tuple.getString("black"), equalTo("omg"));
}
@Test
public void testSelection() {
Tuple tuple = tuple().put("red", "rot").put("brown", "braun").put("blue", "blau").put("yellow", "gelb").put(
"beige", "beige").build();
Tuple selectedTuple = tuple.select("?[key.startsWith('b')]");
assertThat(selectedTuple.size(), equalTo(3));
selectedTuple = tuple.select("^[key.startsWith('b')]");
assertThat(selectedTuple.size(), equalTo(1));
assertThat(selectedTuple.getFieldNames().get(0), equalTo("brown"));
assertThat(selectedTuple.getString(0), equalTo("braun"));
selectedTuple = tuple.select("?[value.length() < 4]");
assertThat(selectedTuple.size(), equalTo(1));
assertThat(selectedTuple.getFieldNames().get(0), equalTo("red"));
assertThat(selectedTuple.getString(0), equalTo("rot"));
}
@Test
public void testReadByteWithDefault() {
// with a value
byte b = 1;
Tuple t = tuple().of("foo", b);
byte defaultByte = 2;
assertTrue(t.getByte(0, defaultByte) == b);
assertTrue(t.getByte("foo", defaultByte) == b);
assertTrue(t.getByte("bar", defaultByte) == defaultByte);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getByte(0, defaultByte) == defaultByte);
assertTrue(t.getByte("foo", defaultByte) == defaultByte);
assertTrue(t.getByte("bar", defaultByte) == defaultByte);
}
@Test
public void testReadShortWithDefault() {
// with a value
short s = 1;
Tuple t = tuple().of("foo", s);
short defaultShort = 2;
assertTrue(t.getShort(0, defaultShort) == s);
assertTrue(t.getShort("foo", defaultShort) == s);
assertTrue(t.getShort("bar", defaultShort) == defaultShort);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getShort(0, defaultShort) == defaultShort);
assertTrue(t.getShort("foo", defaultShort) == defaultShort);
assertTrue(t.getShort("bar", defaultShort) == defaultShort);
}
@Test
public void testReadIntWithDefault() {
// with a value
int i = 1;
Tuple t = tuple().of("foo", i);
int defaultInt = 2;
assertTrue(t.getInt(0, defaultInt) == i);
assertTrue(t.getInt("foo", defaultInt) == i);
assertTrue(t.getInt("bar", defaultInt) == defaultInt);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getInt(0, defaultInt) == defaultInt);
assertTrue(t.getInt("foo", defaultInt) == defaultInt);
assertTrue(t.getInt("bar", defaultInt) == defaultInt);
}
@Test
public void testReadLongWithDefault() {
// with a value
long l = 1;
Tuple t = tuple().of("foo", l);
int defaultLong = 2;
assertTrue(t.getLong(0, defaultLong) == l);
assertTrue(t.getLong("foo", defaultLong) == l);
assertTrue(t.getLong("bar", defaultLong) == defaultLong);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getLong(0, defaultLong) == defaultLong);
assertTrue(t.getLong("foo", defaultLong) == defaultLong);
assertTrue(t.getLong("bar", defaultLong) == defaultLong);
}
@Test
public void testReadFloatWithDefault() {
// with a value
float f = 1;
Tuple t = tuple().of("foo", f);
float defaultFloat = 2.0f;
assertTrue(t.getFloat(0, defaultFloat) == f);
assertTrue(t.getFloat("foo", defaultFloat) == f);
assertTrue(t.getFloat("bar", defaultFloat) == defaultFloat);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getFloat(0, defaultFloat) == defaultFloat);
assertTrue(t.getFloat("foo", defaultFloat) == defaultFloat);
assertTrue(t.getFloat("bar", defaultFloat) == defaultFloat);
}
@Test
public void testReadDoubleWithDefault() {
// with a value
double d = 1;
Tuple t = tuple().of("foo", d);
double defaultDouble = 2.0d;
assertTrue(t.getDouble(0, defaultDouble) == d);
assertTrue(t.getDouble("foo", defaultDouble) == d);
assertTrue(t.getDouble("bar", defaultDouble) == defaultDouble);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getDouble(0, defaultDouble) == defaultDouble);
assertTrue(t.getDouble("foo", defaultDouble) == defaultDouble);
assertTrue(t.getDouble("bar", defaultDouble) == defaultDouble);
}
@Test
public void testReadBigDecimalWithDefault() {
// with a value
BigDecimal bd = new BigDecimal(1);
Tuple t = tuple().of("foo", bd);
BigDecimal defaultBigDecimal = new BigDecimal(2);
assertTrue(t.getBigDecimal(0, defaultBigDecimal) == bd);
assertTrue(t.getBigDecimal("foo", defaultBigDecimal) == bd);
assertTrue(t.getBigDecimal("bar", defaultBigDecimal) == defaultBigDecimal);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getBigDecimal(0, defaultBigDecimal) == defaultBigDecimal);
assertTrue(t.getBigDecimal("foo", defaultBigDecimal) == defaultBigDecimal);
assertTrue(t.getBigDecimal("bar", defaultBigDecimal) == defaultBigDecimal);
}
@Test
public void testReadDateWithDefault() throws InterruptedException {
// with a value
Date date = new Date();
Tuple t = tuple().of("foo", date);
Thread.sleep(1000);
Date defaultDate = new Date();
assertTrue(t.getDate(0, defaultDate) == date);
assertTrue(t.getDate("foo", defaultDate) == date);
assertTrue(t.getDate("bar", defaultDate) == defaultDate);
// with a null value
t = tuple().of("foo", null);
assertTrue(t.getDate(0, defaultDate) == defaultDate);
assertTrue(t.getDate("foo", defaultDate) == defaultDate);
assertTrue(t.getDate("bar", defaultDate) == defaultDate);
}
@Test
public void testReadDateWithPattern() throws ParseException, InterruptedException {
Tuple t = tuple().of("foo", "24-12-2013");
Date d = t.getDateWithPattern(0, "dd-MM-yyyy");
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
assertEquals(dateFormat.parse("24-12-2013"), d);
Thread.sleep(1000);
Date defaultDate = new Date();
assertTrue(t.getDateWithPattern("foo", "xyz-abc", defaultDate) == defaultDate);
assertTrue(t.getDateWithPattern(0, "xyz-abc", defaultDate) == defaultDate);
}
@Test
public void testCollectionToTupleConversionFails() {
thrown.expect(ConverterNotFoundException.class);
Tuple t1 = tuple().of("hello", "world");
Tuple t2 = tuple().of("foo", "bar");
List<Tuple> list = Arrays.asList(t1, t2);
Tuple t = tuple().of("list", list);
t.getTuple("list");
}
}