package com.github.nsnjson.decoding;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
import com.github.nsnjson.AbstractFormatTest;
import org.junit.*;

import static com.github.nsnjson.format.Format.*;

public class DecoderTest extends AbstractFormatTest {

    @Test
    public void processTestNull() {
        shouldDecodeWhenGivenNull(getNull(), getNullPresentation());
    }

    @Test
    public void processTestNumberInt() {
        NumericNode value = getNumberInt();

        shouldDecodeWhenGivenNumber(value, getNumberIntPresentation(value));
    }

    @Test
    public void processTestNumberLong() {
        NumericNode value = getNumberLong();

        shouldDecodeWhenGivenNumber(value, getNumberLongPresentation(value));
    }

    @Test
    public void processTestNumberDouble() {
        NumericNode value = getNumberDouble();

        shouldDecodeWhenGivenNumber(value, getNumberDoublePresentation(value));
    }

    @Test
    public void processTestEmptyString() {
        TextNode value = getEmptyString();

        shouldDecodeWhenGivenString(value, getStringPresentation(value));
    }

    @Test
    public void processTestString() {
        TextNode value = getString();

        shouldDecodeWhenGivenString(value, getStringPresentation(value));
    }

    @Test
    public void processTestBooleanTrue() {
        BooleanNode value = getBooleanTrue();

        shouldDecodeWhenGivenBoolean(value, getBooleanPresentation(value));
    }

    @Test
    public void processTestBooleanFalse() {
        BooleanNode value = getBooleanFalse();

        shouldDecodeWhenGivenBoolean(value, getBooleanPresentation(value));
    }

    @Test
    public void processTestEmptyArray() {
        ArrayNode array = getEmptyArray();

        shouldDecodeWhenGivenArray(array, getArrayPresentation(array));
    }

    @Test
    public void processTestArray() {
        ArrayNode array = getArray();

        shouldDecodeWhenGivenArray(array, getArrayPresentation(array));
    }

    @Test
    public void processTestEmptyObject() {
        ObjectNode object = getEmptyObject();

        shouldDecodeWhenGivenObject(object, getObjectPresentation(object));
    }

    @Test
    public void shouldDecodeWhenGivenObject() {
        ObjectMapper objectMapper = new ObjectMapper();

        String nullField = "null_field";

        String numberIntField = "int_field";

        String numberLongField = "long_field";

        String numberDoubleField = "double_field";

        String stringField = "string_field";

        String booleanTrueField = "true_field";

        String booleanFalseField = "false_field";

        JsonNode numberInt = getNumberInt();

        JsonNode numberLong = getNumberLong();

        JsonNode numberDouble = getNumberDouble();

        JsonNode string = getString();

        JsonNode booleanTrue = getBooleanTrue();

        JsonNode booleanFalse = getBooleanFalse();

        ObjectNode object = objectMapper.createObjectNode();
        object.set(nullField, getNull());
        object.set(numberIntField, numberInt);
        object.set(numberLongField, numberLong);
        object.set(numberDoubleField, numberDouble);
        object.set(stringField, string);
        object.set(booleanTrueField, booleanTrue);
        object.set(booleanFalseField, booleanFalse);

        ObjectNode presentationOfNullField = objectMapper.createObjectNode();
        presentationOfNullField.put(FIELD_NAME, nullField);
        presentationOfNullField.put(FIELD_TYPE, TYPE_MARKER_NULL);

        ObjectNode presentationOfNumberIntField = objectMapper.createObjectNode();
        presentationOfNumberIntField.put(FIELD_NAME, numberIntField);
        presentationOfNumberIntField.put(FIELD_TYPE, TYPE_MARKER_NUMBER);
        presentationOfNumberIntField.put(FIELD_VALUE, numberInt.asInt());

        ObjectNode presentationOfNumberLongField = objectMapper.createObjectNode();
        presentationOfNumberLongField.put(FIELD_NAME, numberLongField);
        presentationOfNumberLongField.put(FIELD_TYPE, TYPE_MARKER_NUMBER);
        presentationOfNumberLongField.put(FIELD_VALUE, numberLong.asLong());

        ObjectNode presentationOfNumberDoubleField = objectMapper.createObjectNode();
        presentationOfNumberDoubleField.put(FIELD_NAME, numberDoubleField);
        presentationOfNumberDoubleField.put(FIELD_TYPE, TYPE_MARKER_NUMBER);
        presentationOfNumberDoubleField.put(FIELD_VALUE, numberDouble.asDouble());

        ObjectNode presentationOfStringField = objectMapper.createObjectNode();
        presentationOfStringField.put(FIELD_NAME, stringField);
        presentationOfStringField.put(FIELD_TYPE, TYPE_MARKER_STRING);
        presentationOfStringField.put(FIELD_VALUE, string.asText());

        ObjectNode presentationOfBooleanTrueField = objectMapper.createObjectNode();
        presentationOfBooleanTrueField.put(FIELD_NAME, booleanTrueField);
        presentationOfBooleanTrueField.put(FIELD_TYPE, TYPE_MARKER_BOOLEAN);
        presentationOfBooleanTrueField.put(FIELD_VALUE, BOOLEAN_TRUE);

        ObjectNode presentationOfBooleanFalseField = objectMapper.createObjectNode();
        presentationOfBooleanFalseField.put(FIELD_NAME, booleanFalseField);
        presentationOfBooleanFalseField.put(FIELD_TYPE, TYPE_MARKER_BOOLEAN);
        presentationOfBooleanFalseField.put(FIELD_VALUE, BOOLEAN_FALSE);

        ArrayNode presentationOfArrayItems = objectMapper.createArrayNode();
        presentationOfArrayItems.add(presentationOfNullField);
        presentationOfArrayItems.add(presentationOfNumberIntField);
        presentationOfArrayItems.add(presentationOfNumberLongField);
        presentationOfArrayItems.add(presentationOfNumberDoubleField);
        presentationOfArrayItems.add(presentationOfStringField);
        presentationOfArrayItems.add(presentationOfBooleanTrueField);
        presentationOfArrayItems.add(presentationOfBooleanFalseField);

        ObjectNode presentation = objectMapper.createObjectNode();
        presentation.put(FIELD_TYPE, TYPE_MARKER_OBJECT);
        presentation.set(FIELD_VALUE, presentationOfArrayItems);

        assertDecoding(object, presentation);
    }

    private void shouldDecodeWhenGivenNull(NullNode value, ObjectNode presentation) {
        assertDecoding(value, presentation);
    }

    private void shouldDecodeWhenGivenNumber(NumericNode value, ObjectNode presentation) {
        assertDecoding(value, presentation);
    }

    private void shouldDecodeWhenGivenString(TextNode value, ObjectNode presentation) {
        assertDecoding(value, presentation);
    }

    private void shouldDecodeWhenGivenBoolean(BooleanNode value, ObjectNode presentation) {
        assertDecoding(value, presentation);
    }

    private void shouldDecodeWhenGivenArray(ArrayNode array, ObjectNode presentation) {
        assertDecoding(array, presentation);
    }

    private void shouldDecodeWhenGivenObject(ObjectNode object, ObjectNode presentation) {
        assertDecoding(object, presentation);
    }

    private static void assertDecoding(JsonNode value, ObjectNode presentation) {
        Assert.assertEquals(value, Decoder.decode(presentation));
    }

}
@@ -2232,3953 +2232,145 @@
 oid 
-shouldDecodeWhenGivenObject() %7B%0A        ObjectMapper objectMapper = new ObjectMapper();%0A%0A        String nullField = %22null_field%22;%0A%0A        String numberIntField = %22int_field%22;%0A%0A        String numberLongField = %22long_field%22;%0A%0A        String numberDoubleField = %22double_field%22;%0A%0A        String stringField = %22string_field%22;%0A%0A        String booleanTrueField = %22true_field%22;%0A%0A        String booleanFalseField = %22false_field%22;%0A%0A        JsonNode numberInt = getNumberInt();%0A%0A        JsonNode numberLong = getNumberLong();%0A%0A        JsonNode numberDouble = getNumberDouble();%0A%0A        JsonNode string = getString();%0A%0A        JsonNode booleanTrue = getBooleanTrue();%0A%0A        JsonNode booleanFalse = getBooleanFalse();%0A%0A        ObjectNode object = objectMapper.createObjectNode();%0A        object.set(nullField, getNull());%0A        object.set(numberIntField, numberInt);%0A        object.set(numberLongField, numberLong);%0A        object.set(numberDoubleField, numberDouble);%0A        object.set(stringField, string);%0A        object.set(booleanTrueField, booleanTrue);%0A        object.set(booleanFalseField, booleanFalse);%0A%0A        ObjectNode presentationOfNullField = objectMapper.createObjectNode();%0A        presentationOfNullField.put(FIELD_NAME, nullField);%0A        presentationOfNullField.put(FIELD_TYPE, TYPE_MARKER_NULL);%0A%0A        ObjectNode presentationOfNumberIntField = objectMapper.createObjectNode();%0A        presentationOfNumberIntField.put(FIELD_NAME, numberIntField);%0A        presentationOfNumberIntField.put(FIELD_TYPE, TYPE_MARKER_NUMBER);%0A        presentationOfNumberIntField.put(FIELD_VALUE, numberInt.asInt());%0A%0A        ObjectNode presentationOfNumberLongField = objectMapper.createObjectNode();%0A        presentationOfNumberLongField.put(FIELD_NAME, numberLongField);%0A        presentationOfNumberLongField.put(FIELD_TYPE, TYPE_MARKER_NUMBER);%0A        presentationOfNumberLongField.put(FIELD_VALUE, numberLong.asLong());%0A%0A        ObjectNode presentationOfNumberDoubleField = objectMapper.createObjectNode();%0A        presentationOfNumberDoubleField.put(FIELD_NAME, numberDoubleField);%0A        presentationOfNumberDoubleField.put(FIELD_TYPE, TYPE_MARKER_NUMBER);%0A        presentationOfNumberDoubleField.put(FIELD_VALUE, numberDouble.asDouble());%0A%0A        ObjectNode presentationOfStringField = objectMapper.createObjectNode();%0A        presentationOfStringField.put(FIELD_NAME, stringField);%0A        presentationOfStringField.put(FIELD_TYPE, TYPE_MARKER_STRING);%0A        presentationOfStringField.put(FIELD_VALUE, string.asText());%0A%0A        ObjectNode presentationOfBooleanTrueField = objectMapper.createObjectNode();%0A        presentationOfBooleanTrueField.put(FIELD_NAME, booleanTrueField);%0A        presentationOfBooleanTrueField.put(FIELD_TYPE, TYPE_MARKER_BOOLEAN);%0A        presentationOfBooleanTrueField.put(FIELD_VALUE, BOOLEAN_TRUE);%0A%0A        ObjectNode presentationOfBooleanFalseField = objectMapper.createObjectNode();%0A        presentationOfBooleanFalseField.put(FIELD_NAME, booleanFalseField);%0A        presentationOfBooleanFalseField.put(FIELD_TYPE, TYPE_MARKER_BOOLEAN);%0A        presentationOfBooleanFalseField.put(FIELD_VALUE, BOOLEAN_FALSE);%0A%0A        ArrayNode presentationOfArrayItems = objectMapper.createArrayNode();%0A        presentationOfArrayItems.add(presentationOfNullField);%0A        presentationOfArrayItems.add(presentationOfNumberIntField);%0A        presentationOfArrayItems.add(presentationOfNumberLongField);%0A        presentationOfArrayItems.add(presentationOfNumberDoubleField);%0A        presentationOfArrayItems.add(presentationOfStringField);%0A        presentationOfArrayItems.add(presentationOfBooleanTrueField);%0A        presentationOfArrayItems.add(presentationOfBooleanFalseField);%0A%0A        ObjectNode presentation = objectMapper.createObjectNode();%0A        presentation.put(FIELD_TYPE, TYPE_MARKER_OBJECT);%0A        presentation.set(FIELD_VALUE, presentationOfArrayItems);%0A%0A        assertDecoding(object, presentation
+processTestObject() %7B%0A        ObjectNode object = getObject();%0A%0A        shouldDecodeWhenGivenObject(object, getObjectPresentation(object)
 );%0A 

Implement test { DecoderTest @ processTestObject }