// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.sdk.internal.protocolparser.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import org.chromium.sdk.internal.JsonUtil;
import org.chromium.sdk.internal.protocolparser.JsonNullable;
import org.chromium.sdk.internal.protocolparser.JsonOptionalField;
import org.chromium.sdk.internal.protocolparser.JsonProtocolModelParseException;
import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
import org.chromium.sdk.internal.protocolparser.JsonType;
import org.chromium.sdk.internal.protocolparser.dynamicimpl.JsonProtocolParser;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.junit.Test;

public class FieldTypesTest {
  @Test
  public void testNullLongValue() throws JsonProtocolModelParseException,
      JsonProtocolParseException {
    JsonProtocolParser parser = new JsonProtocolParser(TypeWithNullableLong.class);

    {
      JSONObject json = parseJson("{'val': 2 }");
      TypeWithNullableLong val = parser.parse(json, TypeWithNullableLong.class);
      assertEquals(2L, val.val());
    }

    {
      JSONObject json = parseJson("{'val': null }");
      TypeWithNullableLong val = parser.parse(json, TypeWithNullableLong.class);
      assertNull(val.val());
    }
  }

  @JsonType
  interface TypeWithNullableLong {
    Long val();
  }

  @Test
  public void testBrokenLongValue() throws JsonProtocolModelParseException,
      JsonProtocolParseException {
    JsonProtocolParser parser = new JsonProtocolParser(TypeWithLong.class);

    {
      JSONObject json = parseJson("{'val': 2 }");
      TypeWithLong val = parser.parse(json, TypeWithLong.class);
      assertEquals(2L, val.val());
    }

    {
      JSONObject json = parseJson("{'val': null }");
      TypeWithLong val = parser.parse(json, TypeWithLong.class);
      try {
        val.val();
        assertTrue(false);
      } catch (Exception e) {
        // expected
      }
    }
  }

  @JsonType
  interface TypeWithLong {
    long val();
  }

  @Test
  public void testNullStructValue() throws JsonProtocolModelParseException,
      JsonProtocolParseException {
    JsonProtocolParser parser = new JsonProtocolParser(Something.class,
        TypeWithNullableSomething.class);

    {
      JSONObject json = parseJson("{'data': {} }");
      TypeWithNullableSomething val = parser.parse(json, TypeWithNullableSomething.class);
      assertNotNull(val.data());
    }

    {
      JSONObject json = parseJson("{'data': null }");
      TypeWithNullableSomething val = parser.parse(json, TypeWithNullableSomething.class);
      assertNull(val.data());
    }
  }

  @JsonType
  interface Something {
  }

  @JsonType
  interface TypeWithNullableSomething {
    @JsonNullable
    Something data();
  }

  @Test
  public void testBrokenNullStructValue() throws JsonProtocolModelParseException,
      JsonProtocolParseException {
    JsonProtocolParser parser = new JsonProtocolParser(Something.class, TypeWithSomething.class);

    {
      JSONObject json = parseJson("{'data': {} }");
      TypeWithSomething val = parser.parse(json, TypeWithSomething.class);
      assertNotNull(val.data());
    }

    {
      JSONObject json = parseJson("{'data': null }");
      try {
        parser.parse(json, TypeWithSomething.class);
        assertTrue(false);
      } catch (Exception e) {
        // expected
      }
    }
  }

  @JsonType
  interface TypeWithSomething {
    Something data();
  }

  @Test
  public void testNonoptionalFields() throws JsonProtocolModelParseException,
      JsonProtocolParseException {
    JsonProtocolParser parser = new JsonProtocolParser(TypeWithNullableLong.class,
        TypeWithSomething.class, Something.class);

    // First couple of checks that parser does work
    {
      JSONObject json = parseJson("{'val': null}");
      TypeWithNullableLong val = parser.parse(json, TypeWithNullableLong.class);
      assertNull(val.val());
    }
    {
      JSONObject json = parseJson("{'data': {} }");
      TypeWithSomething val = parser.parse(json, TypeWithSomething.class);
      assertNotNull(val.data());
    }

    JSONObject emptyJson = parseJson("{}");

    {
      TypeWithNullableLong val = parser.parse(emptyJson, TypeWithNullableLong.class);
      try {
        val.val();
        assertTrue(false);
      } catch (Exception e) {
        // expected
      }
    }
    {
      try {
        TypeWithSomething val = parser.parse(emptyJson, TypeWithSomething.class);
        assertTrue(false);
      } catch (Exception e) {
        // expected
      }
    }
  }

  @Test
  public void testOptionalFields() throws JsonProtocolModelParseException,
      JsonProtocolParseException {
    JsonProtocolParser parser = new JsonProtocolParser(TypeWithOptionalLong.class,
        TypeWithOptionalSomething.class, Something.class);

    JSONObject emptyJson = parseJson("{}");

    {
      TypeWithOptionalLong val = parser.parse(emptyJson, TypeWithOptionalLong.class);
      Long l = val.val();
      assertNull(l);
    }
    {
      TypeWithOptionalSomething val = parser.parse(emptyJson, TypeWithOptionalSomething.class);
      Something something = val.data();
      assertNull(something);
    }
  }

  @JsonType
  interface TypeWithOptionalLong {
    @JsonOptionalField
    Long val();
  }

  @JsonType
  interface TypeWithOptionalSomething {
    @JsonOptionalField
    Something data();
  }

  private JSONObject parseJson(String semiJson) {
    String jsonString = semiJson.replace('\'', '"');
    JSONObject json;
    try {
      json = JsonUtil.jsonObjectFromJson(jsonString);
    } catch (ParseException e) {
      throw new RuntimeException(e);
    }
    return json;
  }
}

@@ -384,26 +384,20 @@
 .Assert.
-assertTrue
+fail
 ;%0A%0Aimpor
@@ -1343,34 +1343,47 @@
    assertEquals(
-2
 L
+ong.valueOf(2)
 , val.val());%0A  
@@ -1992,32 +1992,46 @@
 );%0A    %7D%0A%0A    %7B%0A
+      try %7B%0A  
       JSONObject
@@ -2059,32 +2059,34 @@
 val': null %7D%22);%0A
+  
       TypeWithLo
@@ -2130,36 +2130,24 @@
 ong.class);%0A
-      try %7B%0A
         val.
@@ -2161,32 +2161,21 @@
         
-assertTrue(false
+fail(
 );%0A     
@@ -3581,32 +3581,21 @@
         
-assertTrue(false
+fail(
 );%0A     
@@ -4427,32 +4427,46 @@
 n(%22%7B%7D%22);%0A%0A    %7B%0A
+      try %7B%0A  
       TypeWithNu
@@ -4535,28 +4535,16 @@
 class);%0A
-      try %7B%0A
         
@@ -4562,32 +4562,21 @@
         
-assertTrue(false
+fail(
 );%0A     
@@ -4746,24 +4746,13 @@
     
-assertTrue(false
+fail(
 );%0A 

Make tests robust to "eager parsing" and to 3.5