package org.molgenis.data.support;
import com.google.gson.JsonSyntaxException;
import org.molgenis.data.Entity;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.EntityType;
import org.springframework.core.convert.ConversionFailedException;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.molgenis.data.meta.AttributeType.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
public class StringExpressionEvaluatorTest
{
private Entity entity;
private EntityType entityType;
@BeforeTest
public void createEntity()
{
entityType = when(mock(EntityType.class).getName()).thenReturn("Source").getMock();
Attribute idAttr = when(mock(Attribute.class).getName()).thenReturn("Identifier").getMock();
when(idAttr.getDataType()).thenReturn(INT);
Attribute intAttr = when(mock(Attribute.class).getName()).thenReturn("Int").getMock();
when(intAttr.getDataType()).thenReturn(INT);
Attribute stringAttr = when(mock(Attribute.class).getName()).thenReturn("String").getMock();
when(stringAttr.getDataType()).thenReturn(STRING);
Attribute nonNumericStringAttr = when(mock(Attribute.class).getName()).thenReturn("NonNumericString").getMock();
when(nonNumericStringAttr.getDataType()).thenReturn(STRING);
Attribute longAttr = when(mock(Attribute.class).getName()).thenReturn("Long").getMock();
when(longAttr.getDataType()).thenReturn(LONG);
when(entityType.getIdAttribute()).thenReturn(idAttr);
when(entityType.getAttribute("Identifier")).thenReturn(idAttr);
when(entityType.getAttribute("Int")).thenReturn(intAttr);
when(entityType.getAttribute("String")).thenReturn(stringAttr);
when(entityType.getAttribute("NonNumericString")).thenReturn(nonNumericStringAttr);
when(entityType.getAttribute("Long")).thenReturn(longAttr);
entity = new DynamicEntity(entityType);
entity.set("Int", 1);
entity.set("String", "12");
entity.set("Long", 10L);
entity.set("NonNumericString", "Hello World!");
}
@Test
public void testStringEvaluatorConstructorChecksIfAttributeHasExpression()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#CHROM").getMock();
when(amd.getDataType()).thenReturn(STRING);
try
{
new StringExpressionEvaluator(amd, entityType);
fail("Expected NPE");
}
catch (NullPointerException expected)
{
assertEquals(expected.getMessage(), "Attribute has no expression.");
}
}
@Test
public void testStringEvaluatorConstructorChecksIfExpressionIsMap()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#CHROM").getMock();
when(amd.getDataType()).thenReturn(STRING);
when(amd.getExpression()).thenReturn("{}");
try
{
new StringExpressionEvaluator(amd, entityType);
fail("expected illegal state exception");
}
catch (JsonSyntaxException expected)
{
}
}
@Test
public void testStringEvaluatorConstructorChecksIfAttributeMentionsExistingAttribute()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#CHROM").getMock();
when(amd.getDataType()).thenReturn(STRING);
when(amd.getExpression()).thenReturn("bogus");
try
{
new StringExpressionEvaluator(amd, entityType);
fail("expected illegal argument exception");
}
catch (IllegalArgumentException expected)
{
assertEquals(expected.getMessage(),
"Expression for attribute '#CHROM' references non-existant attribute 'bogus'.");
}
}
@Test
public void testStringEvaluatorLookupAttributeAndConvertFromIntToString()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#CHROM").getMock();
when(amd.getDataType()).thenReturn(STRING);
when(amd.getExpression()).thenReturn("Int");
assertEquals(new StringExpressionEvaluator(amd, entityType).evaluate(entity), "1");
}
@Test
public void testStringEvaluatorLookupAttributeAndConvertFromIntToLong()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#POS").getMock();
when(amd.getDataType()).thenReturn(LONG);
when(amd.getExpression()).thenReturn("Int");
assertEquals(new StringExpressionEvaluator(amd, entityType).evaluate(entity), 1L);
}
@Test
public void testStringEvaluatorLookupAttributeAndConvertFromLongToInt()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#POS").getMock();
when(amd.getDataType()).thenReturn(INT);
when(amd.getExpression()).thenReturn("Long");
assertEquals(new StringExpressionEvaluator(amd, entityType).evaluate(entity), 10);
}
@Test
public void testStringEvaluatorLookupAttributeAndConvertFromStringToLong()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#POS").getMock();
when(amd.getDataType()).thenReturn(LONG);
when(amd.getExpression()).thenReturn("String");
assertEquals(new StringExpressionEvaluator(amd, entityType).evaluate(entity), 12L);
}
@Test(expectedExceptions = ConversionFailedException.class, expectedExceptionsMessageRegExp = "Failed to convert from type \\[java.lang.String\\] to type \\[java.lang.Long\\] for value 'Hello World!'; nested exception is java.lang.NumberFormatException: For input string: \"HelloWorld!\"")
public void testStringEvaluatorLookupAttributeAndConvertFromNonNumericStringToLongFails()
{
Attribute amd = when(mock(Attribute.class).getName()).thenReturn("#POS").getMock();
when(amd.getDataType()).thenReturn(LONG);
when(amd.getExpression()).thenReturn("NonNumericString");
new StringExpressionEvaluator(amd, entityType).evaluate(entity);
}
}