package org.odata4j.test.unit.format.json; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.junit.matchers.JUnitMatchers.containsString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.StringReader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; import org.odata4j.core.OComplexObject; import org.odata4j.format.FormatParser; import org.odata4j.format.FormatParserFactory; import org.odata4j.format.FormatType; import org.odata4j.format.json.JsonFormatParser; import org.odata4j.format.json.JsonStreamReaderFactory; import org.odata4j.format.json.JsonStreamReaderFactory.JsonStreamReader; import org.odata4j.format.json.JsonStreamReaderFactory.JsonStreamReader.JsonEvent; import org.odata4j.format.json.JsonStreamReaderFactory.JsonStreamReader.JsonStartPropertyEvent; import org.odata4j.format.json.JsonStreamReaderFactory.JsonStreamTokenizer; import org.odata4j.format.json.JsonStreamReaderFactory.JsonStreamTokenizer.JsonToken; import org.odata4j.format.json.JsonStreamReaderFactory.JsonStreamTokenizer.JsonTokenType; /** * JSON tokenizer issue */ public class IssueXTest { @Test public void issueX() { String j = "{\n" + "\"d\" : {\n" + "\"OrderID\" : 33, \"ProductID\" : 44\n" + "}\n" + "}"; // issue: the tokenizer emits a NUMBER token for the ProductID value // with value = '44\n' instead of '44' The tokenizer checks number // validity with a NumberFormatter, the JsonTypeConverter.parse // uses Integer.parse for Int32 which pukes on the '\n' StringReader sr = new StringReader(j); JsonStreamTokenizer t = JsonStreamReaderFactory.createJsonStreamTokenizer(sr); JsonToken tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.LEFT_CURLY_BRACKET); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.STRING); Assert.assertTrue(tok.value.equals("d")); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.COLON); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.LEFT_CURLY_BRACKET); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.STRING); Assert.assertTrue(tok.value.equals("OrderID")); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.COLON); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.NUMBER); Assert.assertTrue(tok.value.equals("33")); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.COMMA); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.STRING); Assert.assertTrue(tok.value.equals("ProductID")); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.COLON); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.NUMBER); Assert.assertTrue(tok.value.equals("44")); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.RIGHT_CURLY_BRACKET); tok = t.nextToken(); Assert.assertTrue(tok.type == JsonTokenType.RIGHT_CURLY_BRACKET); } @Test public void issueX0() { String j = "{\n" + "\"d\" : {\n" + "\"OrderID\" : 33, \"ProductID\" : 44\n" + "}\n" + "}"; StringReader sr = new StringReader(j); JsonStreamReader r = JsonStreamReaderFactory.createJsonStreamReader(sr); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isStartObject()); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isStartProperty()); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isStartObject()); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isStartProperty()); Assert.assertTrue(r.hasNext()); JsonEvent e = r.nextEvent(); Assert.assertTrue(e.isEndProperty()); Assert.assertTrue(e.asEndProperty().getValue().equals("33")); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isStartProperty()); Assert.assertTrue(r.hasNext()); e = r.nextEvent(); Assert.assertTrue(e.isEndProperty()); Assert.assertTrue(e.asEndProperty().getValue().equals("44")); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isEndObject()); Assert.assertTrue(r.hasNext()); e = r.nextEvent(); Assert.assertTrue(e.isEndProperty()); Assert.assertTrue(r.hasNext()); Assert.assertTrue(r.nextEvent().isEndObject()); } // TODO rework @Test public void issueX1() { FormatParser<?> fp = FormatParserFactory.getParser(OComplexObject.class, FormatType.JSONVERBOSE, null); JsonStartPropertyEvent e = mock(JsonStartPropertyEvent.class); when(e.getName()).thenReturn("blat"); when(e.isStartProperty()).thenReturn(true); when(e.asStartProperty()).thenReturn(e); try { // call method ensureStartProperty() via reflection; method is protected Method m = JsonFormatParser.class.getDeclaredMethod("ensureStartProperty", JsonEvent.class, String.class); m.setAccessible(true); m.invoke(fp, e, "foobar"); // shouldn't get here but ensureStartProperty has a logic bug. fail(); } catch (InvocationTargetException ex) { Throwable targetException = ex.getTargetException(); assertThat(targetException, instanceOf(IllegalArgumentException.class)); assertThat(targetException.getMessage(), containsString("no valid OData JSON format")); } catch (Exception ex) { fail(ex.toString()); } } }