/**
* Copyright (c) 2009-2015, Christer Sandberg
*/
package se.fishtank.css.selectors.tokenizer;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Tests the {@linkplain se.fishtank.css.selectors.tokenizer.Tokenizer}
*
* @author Christer Sandberg
*/
public class TokenizerTest {
@SuppressWarnings("unchecked")
@Test
public void testTokenizerSpecCompliance() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
TypeReference<List<Object>> typeRef = new TypeReference<List<Object>>() {};
List<Object> list = objectMapper.readValue(getClass().getResource("/component_value_list.json"), typeRef);
int n = 0;
Iterator<Object> iterator = list.iterator();
while (iterator.hasNext()) {
++n;
String input = (String) iterator.next();
LinkedList<Object> tokens = tokenize(input);
List<Object> expected = (List<Object>) iterator.next();
assertEquals("Size mismatch for test number " + n, expected.size(), tokens.size());
int i = 0;
for (Object obj : expected) {
Object token = tokens.get(i);
assertEquals(String.format("Value mismatch at array position %d for test %d: %s (%s != %s)",
i, n, input, token, obj), obj, token);
++i;
}
}
}
public LinkedList<Object> tokenize(String input) {
LinkedList<Object> result = new LinkedList<Object>();
Tokenizer tokenizer = new Tokenizer(input);
while (true) {
Object value;
Token token = tokenizer.nextToken();
switch (token.type) {
case EOF:
return result;
case AT_KEYWORD:
value = values("at-keyword", token.value);
break;
case BAD_STRING:
value = values("error", "bad-string");
break;
case BAD_URL:
value = values("error", "bad-url");
break;
case FUNCTION:
value = values("function", token.value);
break;
case HASH:
Token.Hash h = (Token.Hash) token;
String hashFlag = h.id ? "id" : "unrestricted";
value = values("hash", h.value, hashFlag);
break;
case IDENT:
value = values("ident", token.value);
break;
case STRING:
value = values("string", token.value);
break;
case URL:
value = values("url", token.value);
break;
case WHITESPACE:
value = " ";
break;
case DIMENSION:
Token.Dimension d = (Token.Dimension) token;
String dimensionFlag = d.integer ? "integer": "number";
value = values("dimension", d.value, number(d.value, d.integer), dimensionFlag, d.unit);
break;
case NUMBER:
case PERCENTAGE:
Token.Number n = (Token.Number) token;
String numberFlag = n.integer ? "integer": "number";
String tokenType = token.type == TokenType.PERCENTAGE ? "percentage": "number";
value = values(tokenType, n.value, number(n.value, n.integer), numberFlag);
break;
case UNICODE_RANGE:
Token.UnicodeRange u = (Token.UnicodeRange) token;
value = values("unicode-range", u.start, u.end);
break;
default:
value = token.value;
}
result.add(value);
}
}
private Object number(String value, boolean integer) {
if (integer) {
return Integer.parseInt(value);
}
double d = Double.parseDouble(value);
if ((d % 1) == 0) {
return (int) d;
}
return d;
}
private static List<Object> values(Object... values) {
return Arrays.asList(values);
}
}