json/src/test/java/net/java/html/json/ModelProcessorTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Wed, 28 Oct 2015 19:29:17 +0100
changeset 1011 267ca1bfeb6f
parent 955 8e0439c4cc72
child 1023 4f906bde3a2e
permissions -rw-r--r--
#256178: Only generate the constructor with arguments if it can be compiled - e.g. if the number of arguments in not higher than 255.
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    31  *
    32  * If you wish your version of this file to be governed by only the CDDL
    33  * or only the GPL Version 2, indicate your decision by adding
    34  * "[Contributor] elects to include this software in this distribution
    35  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    36  * single choice of license, a recipient has the option to distribute
    37  * your version of this file under either the CDDL, the GPL Version 2 or
    38  * to extend the choice of license to its licensees as provided above.
    39  * However, if you add GPL Version 2 code and therefore, elected the GPL
    40  * Version 2 license, then the option applies only if the new code is
    41  * made subject to such option by the copyright holder.
    42  */
    43 package net.java.html.json;
    44 
    45 import java.io.IOException;
    46 import java.util.Locale;
    47 import javax.tools.Diagnostic;
    48 import javax.tools.JavaFileObject;
    49 import static org.testng.Assert.*;
    50 import org.testng.annotations.Test;
    51 
    52 /** Verify errors emitted by the processor.
    53  *
    54  * @author Jaroslav Tulach
    55  */
    56 public class ModelProcessorTest {
    57     @Test public void verifyWrongType() throws IOException {
    58         String html = "<html><body>"
    59             + "</body></html>";
    60         String code = "package x.y.z;\n"
    61             + "import net.java.html.json.Model;\n"
    62             + "import net.java.html.json.Property;\n"
    63             + "@Model(className=\"XModel\", properties={\n"
    64             + "  @Property(name=\"prop\", type=Runnable.class)\n"
    65             + "})\n"
    66             + "class X {\n"
    67             + "}\n";
    68 
    69         Compile c = Compile.create(html, code);
    70         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
    71         boolean ok = false;
    72         StringBuilder msgs = new StringBuilder();
    73         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
    74             String msg = e.getMessage(Locale.ENGLISH);
    75             if (msg.contains("Runnable")) {
    76                 ok = true;
    77             }
    78             msgs.append("\n").append(msg);
    79         }
    80         if (!ok) {
    81             fail("Should contain warning about Runnable:" + msgs);
    82         }
    83     }
    84 
    85     @Test public void verifyWrongTypeInInnerClass() throws IOException {
    86         String html = "<html><body>"
    87             + "</body></html>";
    88         String code = "package x.y.z;\n"
    89             + "import net.java.html.json.Model;\n"
    90             + "import net.java.html.json.Property;\n"
    91             + "class X {\n"
    92             + "  @Model(className=\"XModel\", properties={\n"
    93             + "    @Property(name=\"prop\", type=Runnable.class)\n"
    94             + "  })\n"
    95             + "  static class Inner {\n"
    96             + "  }\n"
    97             + "}\n";
    98 
    99         Compile c = Compile.create(html, code);
   100         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   101         boolean ok = false;
   102         StringBuilder msgs = new StringBuilder();
   103         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   104             String msg = e.getMessage(Locale.ENGLISH);
   105             if (msg.contains("Runnable")) {
   106                 ok = true;
   107             }
   108             msgs.append("\n").append(msg);
   109         }
   110         if (!ok) {
   111             fail("Should contain warning about Runnable:" + msgs);
   112         }
   113     }
   114 
   115     @Test public void warnOnNonStatic() throws IOException {
   116         String html = "<html><body>"
   117             + "</body></html>";
   118         String code = "package x.y.z;\n"
   119             + "import net.java.html.json.Model;\n"
   120             + "import net.java.html.json.Property;\n"
   121             + "import net.java.html.json.ComputedProperty;\n"
   122             + "@Model(className=\"XModel\", properties={\n"
   123             + "  @Property(name=\"prop\", type=int.class)\n"
   124             + "})\n"
   125             + "class X {\n"
   126             + "    @ComputedProperty int y(int prop) {\n"
   127             + "        return prop;\n"
   128             + "    }\n"
   129             + "}\n";
   130 
   131         Compile c = Compile.create(html, code);
   132         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   133         boolean ok = false;
   134         StringBuilder msgs = new StringBuilder();
   135         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   136             String msg = e.getMessage(Locale.ENGLISH);
   137             if (msg.contains("y has to be static")) {
   138                 ok = true;
   139             }
   140             msgs.append("\n").append(msg);
   141         }
   142         if (!ok) {
   143             fail("Should contain warning about non-static method:" + msgs);
   144         }
   145     }
   146 
   147     @Test public void tooManyProperties() throws IOException {
   148         manyProperties(255, false, 0);
   149     }
   150 
   151     @Test public void tooManyArrayPropertiesIsOK() throws IOException {
   152         manyProperties(0, true, 300);
   153     }
   154 
   155     @Test public void justEnoughProperties() throws IOException {
   156         manyProperties(254, true, 0);
   157     }
   158 
   159     @Test public void justEnoughPropertiesWithArrayOne() throws IOException {
   160         manyProperties(253, true, 300);
   161     }
   162 
   163     @Test public void justEnoughPropertiesButOneArrayOne() throws IOException {
   164         manyProperties(254, false, 300);
   165     }
   166 
   167     private void manyProperties(
   168         int cnt, boolean constructorWithParams, int arrayCnt
   169     ) throws IOException {
   170         String html = "<html><body>"
   171             + "</body></html>";
   172         StringBuilder code = new StringBuilder();
   173         code.append("package x.y.z;\n"
   174             + "import net.java.html.json.Model;\n"
   175             + "import net.java.html.json.Property;\n"
   176             + "@Model(className=\"XModel\", properties={\n"
   177         );
   178         for (int i = 1; i <= cnt; i++) {
   179             code.append("  @Property(name=\"prop").append(i).append("\", ");
   180             code.append("type=int.class),\n");
   181         }
   182         for (int i = 1; i <= arrayCnt; i++) {
   183             code.append("  @Property(name=\"array").append(i).append("\", ");
   184             code.append("array=true, ");
   185             code.append("type=int.class),\n");
   186         }
   187         code.append(""
   188             + "})\n"
   189             + "class X {\n"
   190             + "    static {\n"
   191             + "      new XModel();\n"
   192             + "      new XModel("
   193         );
   194         if (constructorWithParams) {
   195             code.append("0");
   196             for (int i = 1; i < cnt; i++) {
   197                 code.append(",\n").append(i);
   198             }
   199         }
   200         code.append(");\n"
   201             + "    }\n"
   202             + "}\n"
   203         );
   204 
   205         Compile c = Compile.create(html, code.toString());
   206         assertTrue(c.getErrors().isEmpty(), "Compiles OK: " + c.getErrors());
   207     }
   208 
   209     @Test public void writeableComputedPropertyMissingWrite() throws IOException {
   210         String html = "<html><body>"
   211             + "</body></html>";
   212         String code = "package x.y.z;\n"
   213             + "import net.java.html.json.Model;\n"
   214             + "import net.java.html.json.Property;\n"
   215             + "import net.java.html.json.ComputedProperty;\n"
   216             + "@Model(className=\"XModel\", properties={\n"
   217             + "  @Property(name=\"prop\", type=int.class)\n"
   218             + "})\n"
   219             + "class X {\n"
   220             + "    static @ComputedProperty(write=\"setY\") int y(int prop) {\n"
   221             + "        return prop;\n"
   222             + "    }\n"
   223             + "}\n";
   224 
   225         Compile c = Compile.create(html, code);
   226         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   227         boolean ok = false;
   228         StringBuilder msgs = new StringBuilder();
   229         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   230             String msg = e.getMessage(Locale.ENGLISH);
   231             if (msg.contains("Cannot find setY")) {
   232                 ok = true;
   233             }
   234             msgs.append("\n").append(msg);
   235         }
   236         if (!ok) {
   237             fail("Should contain warning about non-static method:" + msgs);
   238         }
   239     }
   240 
   241     @Test public void writeableComputedPropertyWrongWriteType() throws IOException {
   242         String html = "<html><body>"
   243             + "</body></html>";
   244         String code = "package x.y.z;\n"
   245             + "import net.java.html.json.Model;\n"
   246             + "import net.java.html.json.Property;\n"
   247             + "import net.java.html.json.ComputedProperty;\n"
   248             + "@Model(className=\"XModel\", properties={\n"
   249             + "  @Property(name=\"prop\", type=int.class)\n"
   250             + "})\n"
   251             + "class X {\n"
   252             + "    static @ComputedProperty(write=\"setY\") int y(int prop) {\n"
   253             + "        return prop;\n"
   254             + "    }\n"
   255             + "    static void setY(XModel model, String prop) {\n"
   256             + "    }\n"
   257             + "}\n";
   258 
   259         Compile c = Compile.create(html, code);
   260         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   261         boolean ok = false;
   262         StringBuilder msgs = new StringBuilder();
   263         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   264             String msg = e.getMessage(Locale.ENGLISH);
   265             if (msg.contains("Write method first argument needs to be XModel and second int or Object")) {
   266                 ok = true;
   267             }
   268             msgs.append("\n").append(msg);
   269         }
   270         if (!ok) {
   271             fail("Should contain warning about non-static method:" + msgs);
   272         }
   273     }
   274 
   275     @Test public void writeableComputedPropertyReturnsVoid() throws IOException {
   276         String html = "<html><body>"
   277             + "</body></html>";
   278         String code = "package x.y.z;\n"
   279             + "import net.java.html.json.Model;\n"
   280             + "import net.java.html.json.Property;\n"
   281             + "import net.java.html.json.ComputedProperty;\n"
   282             + "@Model(className=\"XModel\", properties={\n"
   283             + "  @Property(name=\"prop\", type=int.class)\n"
   284             + "})\n"
   285             + "class X {\n"
   286             + "    static @ComputedProperty(write=\"setY\") int y(int prop) {\n"
   287             + "        return prop;\n"
   288             + "    }\n"
   289             + "    static Number setY(XModel model, int prop) {\n"
   290             + "    }\n"
   291             + "}\n";
   292 
   293         Compile c = Compile.create(html, code);
   294         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   295         boolean ok = false;
   296         StringBuilder msgs = new StringBuilder();
   297         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   298             String msg = e.getMessage(Locale.ENGLISH);
   299             if (msg.contains("Write method has to return void")) {
   300                 ok = true;
   301             }
   302             msgs.append("\n").append(msg);
   303         }
   304         if (!ok) {
   305             fail("Should contain warning about non-static method:" + msgs);
   306         }
   307     }
   308 
   309     @Test public void computedCantReturnVoid() throws IOException {
   310         String html = "<html><body>"
   311             + "</body></html>";
   312         String code = "package x.y.z;\n"
   313             + "import net.java.html.json.Model;\n"
   314             + "import net.java.html.json.Property;\n"
   315             + "import net.java.html.json.ComputedProperty;\n"
   316             + "@Model(className=\"XModel\", properties={\n"
   317             + "  @Property(name=\"prop\", type=int.class)\n"
   318             + "})\n"
   319             + "class X {\n"
   320             + "    @ComputedProperty static void y(int prop) {\n"
   321             + "    }\n"
   322             + "}\n";
   323 
   324         Compile c = Compile.create(html, code);
   325         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   326         boolean ok = false;
   327         StringBuilder msgs = new StringBuilder();
   328         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   329             String msg = e.getMessage(Locale.ENGLISH);
   330             if (msg.contains("y cannot return void")) {
   331                 ok = true;
   332             }
   333             msgs.append("\n").append(msg);
   334         }
   335         if (!ok) {
   336             fail("Should contain warning about non-static method:" + msgs);
   337         }
   338     }
   339 
   340     @Test public void computedCantReturnRunnable() throws IOException {
   341         String html = "<html><body>"
   342             + "</body></html>";
   343         String code = "package x.y.z;\n"
   344             + "import net.java.html.json.Model;\n"
   345             + "import net.java.html.json.Property;\n"
   346             + "import net.java.html.json.ComputedProperty;\n"
   347             + "@Model(className=\"XModel\", properties={\n"
   348             + "  @Property(name=\"prop\", type=int.class)\n"
   349             + "})\n"
   350             + "class X {\n"
   351             + "    @ComputedProperty static Runnable y(int prop) {\n"
   352             + "       return null;\n"
   353             + "    }\n"
   354             + "}\n";
   355 
   356         Compile c = Compile.create(html, code);
   357         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   358         boolean ok = false;
   359         StringBuilder msgs = new StringBuilder();
   360         for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   361             String msg = e.getMessage(Locale.ENGLISH);
   362             if (msg.contains("y cannot return java.lang.Runnable")) {
   363                 ok = true;
   364             }
   365             msgs.append("\n").append(msg);
   366         }
   367         if (!ok) {
   368             fail("Should contain warning about non-static method:" + msgs);
   369         }
   370     }
   371 
   372     @Test public void canWeCompileWithJDK1_5SourceLevel() throws IOException {
   373         String html = "<html><body>"
   374             + "</body></html>";
   375         String code = "package x.y.z;\n"
   376             + "import net.java.html.json.Model;\n"
   377             + "import net.java.html.json.Property;\n"
   378             + "import net.java.html.json.ComputedProperty;\n"
   379             + "@Model(className=\"XModel\", properties={\n"
   380             + "  @Property(name=\"prop\", type=long.class)\n"
   381             + "})\n"
   382             + "class X {\n"
   383             + "  @ComputedProperty static double derived(long prop) { return prop; }"
   384             + "}\n";
   385 
   386         Compile c = Compile.create(html, code, "1.5");
   387         assertTrue(c.getErrors().isEmpty(), "No errors: " + c.getErrors());
   388     }
   389 
   390     @Test public void putNeedsDataArgument() throws Exception {
   391         needsAnArg("PUT");
   392     }
   393 
   394     @Test public void postNeedsDataArgument() throws Exception {
   395         needsAnArg("POST");
   396     }
   397 
   398     private void needsAnArg(String method) throws Exception {
   399         String html = "<html><body>"
   400             + "</body></html>";
   401         String code = "package x.y.z;\n"
   402             + "import net.java.html.json.Model;\n"
   403             + "import net.java.html.json.Property;\n"
   404             + "import net.java.html.json.OnReceive;\n"
   405             + "@Model(className=\"XModel\", properties={\n"
   406             + "  @Property(name=\"prop\", type=long.class)\n"
   407             + "})\n"
   408             + "class X {\n"
   409             + "  @Model(className=\"PQ\", properties={})\n"
   410             + "  class PImpl {\n"
   411             + "  }\n"
   412             + "  @OnReceive(method=\"" + method + "\", url=\"whereever\")\n"
   413             + "  static void obtained(XModel m, PQ p) { }\n"
   414             + "}\n";
   415 
   416         Compile c = Compile.create(html, code);
   417         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   418         for (Diagnostic<? extends JavaFileObject> diagnostic : c.getErrors()) {
   419             String msg = diagnostic.getMessage(Locale.ENGLISH);
   420             if (msg.contains("specify a data()")) {
   421                 return;
   422             }
   423         }
   424         fail("Needs an error message about missing data():\n" + c.getErrors());
   425 
   426     }
   427 
   428 
   429     @Test public void jsonNeedsToUseGet () throws Exception {
   430         String html = "<html><body>"
   431             + "</body></html>";
   432         String code = "package x.y.z;\n"
   433             + "import net.java.html.json.Model;\n"
   434             + "import net.java.html.json.Property;\n"
   435             + "import net.java.html.json.OnReceive;\n"
   436             + "@Model(className=\"XModel\", properties={\n"
   437             + "  @Property(name=\"prop\", type=long.class)\n"
   438             + "})\n"
   439             + "class X {\n"
   440             + "  @Model(className=\"PQ\", properties={})\n"
   441             + "  class PImpl {\n"
   442             + "  }\n"
   443             + "  @OnReceive(method=\"POST\", jsonp=\"callback\", url=\"whereever\")\n"
   444             + "  static void obtained(XModel m, PQ p) { }\n"
   445             + "}\n";
   446 
   447         Compile c = Compile.create(html, code);
   448         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   449         for (Diagnostic<? extends JavaFileObject> diagnostic : c.getErrors()) {
   450             String msg = diagnostic.getMessage(Locale.ENGLISH);
   451             if (msg.contains("JSONP works only with GET")) {
   452                 return;
   453             }
   454         }
   455         fail("Needs an error message about wrong method:\n" + c.getErrors());
   456 
   457     }
   458 
   459     @Test public void noHeadersForWebSockets() throws Exception {
   460         String html = "<html><body>"
   461             + "</body></html>";
   462         String code = "package x.y.z;\n"
   463             + "import net.java.html.json.Model;\n"
   464             + "import net.java.html.json.Property;\n"
   465             + "import net.java.html.json.OnReceive;\n"
   466             + "@Model(className=\"XModel\", properties={\n"
   467             + "  @Property(name=\"prop\", type=long.class)\n"
   468             + "})\n"
   469             + "class X {\n"
   470             + "  @Model(className=\"PQ\", properties={})\n"
   471             + "  class PImpl {\n"
   472             + "  }\n"
   473             + "  @OnReceive(method=\"WebSocket\", data = PQ.class, headers=\"SomeHeader: {some}\", url=\"whereever\")\n"
   474             + "  static void obtained(XModel m, PQ p) { }\n"
   475             + "}\n";
   476 
   477         Compile c = Compile.create(html, code);
   478         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   479         for (Diagnostic<? extends JavaFileObject> diagnostic : c.getErrors()) {
   480             String msg = diagnostic.getMessage(Locale.ENGLISH);
   481             if (msg.contains("WebSocket spec does not support headers")) {
   482                 return;
   483             }
   484         }
   485         fail("Needs an error message about headers:\n" + c.getErrors());
   486 
   487     }
   488 
   489     @Test public void webSocketsWithoutDataIsError() throws Exception {
   490         String html = "<html><body>"
   491             + "</body></html>";
   492         String code = "package x.y.z;\n"
   493             + "import net.java.html.json.Model;\n"
   494             + "import net.java.html.json.Property;\n"
   495             + "import net.java.html.json.OnReceive;\n"
   496             + "@Model(className=\"XModel\", properties={\n"
   497             + "  @Property(name=\"prop\", type=long.class)\n"
   498             + "})\n"
   499             + "class X {\n"
   500             + "  @Model(className=\"PQ\", properties={})\n"
   501             + "  class PImpl {\n"
   502             + "  }\n"
   503             + "  @OnReceive(method=\"WebSocket\", url=\"whereever\")\n"
   504             + "  static void obtained(XModel m, PQ p) { }\n"
   505             + "}\n";
   506 
   507         Compile c = Compile.create(html, code);
   508         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   509         for (Diagnostic<? extends JavaFileObject> diagnostic : c.getErrors()) {
   510             String msg = diagnostic.getMessage(Locale.ENGLISH);
   511             if (msg.contains("eeds to specify a data()")) {
   512                 return;
   513             }
   514         }
   515         fail("Needs data attribute :\n" + c.getErrors());
   516     }
   517 
   518     @Test public void noNewLinesInHeaderLines() throws Exception {
   519         String html = "<html><body>"
   520             + "</body></html>";
   521         String code = "package x.y.z;\n"
   522             + "import net.java.html.json.Model;\n"
   523             + "import net.java.html.json.Property;\n"
   524             + "import net.java.html.json.OnReceive;\n"
   525             + "@Model(className=\"XModel\", properties={\n"
   526             + "  @Property(name=\"prop\", type=long.class)\n"
   527             + "})\n"
   528             + "class X {\n"
   529             + "  @Model(className=\"PQ\", properties={})\n"
   530             + "  class PImpl {\n"
   531             + "  }\n"
   532             + "  @OnReceive(headers=\"SomeHeader\\n: {some}\", url=\"whereever\")\n"
   533             + "  static void obtained(XModel m, PQ p) { }\n"
   534             + "}\n";
   535 
   536         Compile c = Compile.create(html, code);
   537         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   538         for (Diagnostic<? extends JavaFileObject> diagnostic : c.getErrors()) {
   539             String msg = diagnostic.getMessage(Locale.ENGLISH);
   540             if (msg.contains("Header line cannot contain line separator")) {
   541                 return;
   542             }
   543         }
   544         fail("Needs an error message about headers:\n" + c.getErrors());
   545 
   546     }
   547 
   548     @Test public void noReturnInHeaderLines() throws Exception {
   549         String html = "<html><body>"
   550             + "</body></html>";
   551         String code = "package x.y.z;\n"
   552             + "import net.java.html.json.Model;\n"
   553             + "import net.java.html.json.Property;\n"
   554             + "import net.java.html.json.OnReceive;\n"
   555             + "@Model(className=\"XModel\", properties={\n"
   556             + "  @Property(name=\"prop\", type=long.class)\n"
   557             + "})\n"
   558             + "class X {\n"
   559             + "  @Model(className=\"PQ\", properties={})\n"
   560             + "  class PImpl {\n"
   561             + "  }\n"
   562             + "  @OnReceive(headers=\"Some\\rHeader: {some}\", url=\"whereever\")\n"
   563             + "  static void obtained(XModel m, PQ p) { }\n"
   564             + "}\n";
   565 
   566         Compile c = Compile.create(html, code);
   567         assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   568         for (Diagnostic<? extends JavaFileObject> diagnostic : c.getErrors()) {
   569             String msg = diagnostic.getMessage(Locale.ENGLISH);
   570             if (msg.contains("Header line cannot contain line separator")) {
   571                 return;
   572             }
   573         }
   574         fail("Needs an error message about headers:\n" + c.getErrors());
   575 
   576     }
   577 
   578     @Test public void onErrorHasToExist() throws IOException {
   579         Compile res = Compile.create("", "package x;\n"
   580             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   581             + "  @net.java.html.json.Property(name=\"x\", type=String.class)\n"
   582             + "})\n"
   583             + "class UseOnReceive {\n"
   584             + "  @net.java.html.json.OnReceive(url=\"http://nowhere.com\", onError=\"doesNotExist\")\n"
   585             + "  static void onMessage(MyModel model, String value) {\n"
   586             + "  }\n"
   587             + "}\n"
   588         );
   589         res.assertErrors();
   590         res.assertError("not find doesNotExist");
   591     }
   592 
   593     @Test public void usingListIsOK() throws IOException {
   594         Compile res = Compile.create("", "package x;\n"
   595             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   596             + "  @net.java.html.json.Property(name=\"x\", type=String.class)\n"
   597             + "})\n"
   598             + "class UseOnReceive {\n"
   599             + "  @net.java.html.json.OnReceive(url=\"http://nowhere.com\")\n"
   600             + "  static void onMessage(MyModel model, java.util.List<MyData> value) {\n"
   601             + "  }\n"
   602             + "\n"
   603             + "  @net.java.html.json.Model(className=\"MyData\", properties={\n"
   604             + "  })\n"
   605             + "  static class MyDataModel {\n"
   606             + "  }\n"
   607             + "}\n"
   608         );
   609         res.assertNoErrors();
   610     }
   611 
   612     @Test public void functionAndPropertyCollide() throws IOException {
   613         Compile res = Compile.create("", "package x;\n"
   614             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   615             + "  @net.java.html.json.Property(name=\"x\", type=String.class)\n"
   616             + "})\n"
   617             + "class Collision {\n"
   618             + "  @net.java.html.json.Function\n"
   619             + "  static void x(MyModel model, String value) {\n"
   620             + "  }\n"
   621             + "}\n"
   622         );
   623         res.assertErrors();
   624         res.assertError("cannot have the name");
   625     }
   626 
   627     @Test public void twoPropertiesCollide() throws IOException {
   628         Compile res = Compile.create("", "package x;\n"
   629             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   630             + "  @net.java.html.json.Property(name=\"x\", type=String.class),\n"
   631             + "  @net.java.html.json.Property(name=\"x\", type=int.class)\n"
   632             + "})\n"
   633             + "class Collision {\n"
   634             + "}\n"
   635         );
   636         res.assertErrors();
   637         res.assertError("Cannot have the name");
   638     }
   639 
   640     @Test public void propertyAndComputedOneCollide() throws IOException {
   641         Compile res = Compile.create("", "package x;\n"
   642             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   643             + "  @net.java.html.json.Property(name=\"x\", type=String.class),\n"
   644             + "})\n"
   645             + "class Collision {\n"
   646             + "  @net.java.html.json.ComputedProperty static int x(String x) {\n"
   647             + "    return x.length();\n"
   648             + "  }\n"
   649             + "}\n"
   650         );
   651         res.assertErrors();
   652         res.assertError("Cannot have the name");
   653     }
   654 
   655     @Test public void onWebSocketJustTwoArgs() throws IOException {
   656         Compile res = Compile.create("", "package x;\n"
   657             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   658             + "  @net.java.html.json.Property(name=\"x\", type=String.class)\n"
   659             + "})\n"
   660             + "class UseOnReceive {\n"
   661             + "  @net.java.html.json.OnReceive(url=\"http://nowhere.com\", method=\"WebSocket\", data=String.class)\n"
   662             + "  static void onMessage(MyModel model, String value, int arg) {\n"
   663             + "  }\n"
   664             + "}\n"
   665         );
   666         res.assertErrors();
   667         res.assertError("only have two arg");
   668     }
   669 
   670     @Test public void onErrorWouldHaveToBeStatic() throws IOException {
   671         Compile res = Compile.create("", "package x;\n"
   672             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   673             + "  @net.java.html.json.Property(name=\"x\", type=String.class)\n"
   674             + "})\n"
   675             + "class UseOnReceive {\n"
   676             + "  @net.java.html.json.OnReceive(url=\"http://nowhere.com\", onError=\"notStatic\")\n"
   677             + "  static void onMessage(MyModel model, String value) {\n"
   678             + "  }\n"
   679             + "  void notStatic(Exception e) {}\n"
   680             + "}\n"
   681         );
   682         res.assertErrors();
   683         res.assertError("have to be static");
   684     }
   685 
   686     @Test public void onErrorMustAcceptExceptionArgument() throws IOException {
   687         Compile res = Compile.create("", "package x;\n"
   688             + "@net.java.html.json.Model(className=\"MyModel\", properties= {\n"
   689             + "  @net.java.html.json.Property(name=\"x\", type=String.class)\n"
   690             + "})\n"
   691             + "class UseOnReceive {\n"
   692             + "  @net.java.html.json.OnReceive(url=\"http://nowhere.com\", onError=\"subclass\")\n"
   693             + "  static void onMessage(MyModel model, String value) {\n"
   694             + "  }\n"
   695             + "  static void subclass(java.io.IOException e) {}\n"
   696             + "}\n"
   697         );
   698         res.assertErrors();
   699         res.assertError("Error method first argument needs to be MyModel and second Exception");
   700     }
   701 }