json/src/test/java/net/java/html/json/ModelTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 790 30f20d9c0986
child 920 117b732d42d0
permissions -rw-r--r--
During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
     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 net.java.html.BrwsrCtx;
    46 import java.util.ArrayList;
    47 import java.util.Collections;
    48 import java.util.Iterator;
    49 import java.util.List;
    50 import java.util.ListIterator;
    51 import org.netbeans.html.context.spi.Contexts;
    52 import org.netbeans.html.json.spi.FunctionBinding;
    53 import org.netbeans.html.json.spi.PropertyBinding;
    54 import org.netbeans.html.json.spi.Technology;
    55 import static org.testng.Assert.*;
    56 import org.testng.annotations.BeforeMethod;
    57 import org.testng.annotations.Test;
    58 
    59 /**
    60  *
    61  * @author Jaroslav Tulach
    62  */
    63 @Model(className = "Modelik", properties = {
    64     @Property(name = "value", type = int.class),
    65     @Property(name = "count", type = int.class),
    66     @Property(name = "unrelated", type = long.class),
    67     @Property(name = "names", type = String.class, array = true),
    68     @Property(name = "values", type = int.class, array = true),
    69     @Property(name = "people", type = Person.class, array = true),
    70     @Property(name = "changedProperty", type=String.class)
    71 })
    72 public class ModelTest {
    73     private MockTechnology my;
    74     private Modelik model;
    75     private static Modelik leakedModel;
    76     
    77     @BeforeMethod
    78     public void createModel() {
    79         my = new MockTechnology();
    80         final BrwsrCtx c = Contexts.newBuilder().register(Technology.class, my, 1).build();
    81         model = Models.bind(new Modelik(), c);
    82     }
    83     
    84     @Test public void classGeneratedWithSetterGetter() {
    85         model.setValue(10);
    86         assertEquals(10, model.getValue(), "Value changed");
    87     }
    88     
    89     @Test public void computedMethod() {
    90         model.setValue(4);
    91         assertEquals(16, model.getPowerValue());
    92     }
    93     
    94     @Test public void equalsAndHashCode() {
    95         Modelik m1 = new Modelik(10, 20, 30, "changed", "firstName");
    96         Modelik m2 = new Modelik(10, 20, 30, "changed", "firstName");
    97         
    98         assertTrue(m1.equals(m2), "They are the same");
    99         assertEquals(m1.hashCode(), m2.hashCode(), "Hashcode is the same");
   100         
   101         m1.setCount(33);
   102         
   103         assertFalse(m1.equals(m2), "No longer the same");
   104         assertFalse(m1.hashCode() == m2.hashCode(), "No longe is hashcode is the same");
   105     }
   106     
   107     @Test public void arrayIsMutable() {
   108         assertEquals(model.getNames().size(), 0, "Is empty");
   109         model.getNames().add("Jarda");
   110         assertEquals(model.getNames().size(), 1, "One element");
   111     }
   112 
   113     @Test public void arrayChangesNotNotifiedUntilInitied() {
   114         model.getNames().add("Hello");
   115         assertTrue(my.mutated.isEmpty(), "No change now " + my.mutated);
   116         model.getNames().remove("Hello");
   117         assertTrue(my.mutated.isEmpty(), "No change still " + my.mutated);
   118         assertTrue(model.getNames().isEmpty(), "No empty");
   119     }
   120     
   121     @Test public void arrayChangesNotified() {
   122         Models.applyBindings(model);
   123         model.getNames().add("Hello");
   124         
   125         assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
   126         assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
   127 
   128         my.mutated.clear();
   129         
   130         Iterator<String> it = model.getNames().iterator();
   131         assertEquals(it.next(), "Hello");
   132         it.remove();
   133         
   134         assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
   135         assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
   136 
   137         my.mutated.clear();
   138         
   139         ListIterator<String> lit = model.getNames().listIterator();
   140         lit.add("Jarda");
   141         
   142         assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
   143         assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
   144     }
   145 
   146     @Test public void autoboxedArray() {
   147         model.getValues().add(10);
   148         
   149         assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
   150     }
   151 
   152     @Test public void derivedArrayProp() {
   153         model.applyBindings();
   154         model.setCount(10);
   155         
   156         List<String> arr = model.getRepeat();
   157         assertEquals(arr.size(), 10, "Ten items: " + arr);
   158         
   159         my.mutated.clear();
   160         
   161         model.setCount(5);
   162         
   163         arr = model.getRepeat();
   164         assertEquals(arr.size(), 5, "Five items: " + arr);
   165 
   166         assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
   167         assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
   168         assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
   169     }
   170     
   171     @Test public void derivedPropertiesAreNotified() {
   172         model.applyBindings();
   173         
   174         model.setValue(33);
   175         
   176         // not interested in change of this property
   177         my.mutated.remove("changedProperty");
   178         
   179         assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
   180         assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
   181         assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
   182         
   183         my.mutated.clear();
   184         
   185         model.setUnrelated(44);
   186         
   187         
   188         // not interested in change of this property
   189         my.mutated.remove("changedProperty");
   190         assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
   191         assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
   192     }
   193 
   194     @Test public void computedPropertyCannotWriteToModel() {
   195         leakedModel = model;
   196         try {
   197             String res = model.getNotAllowedWrite();
   198             fail("We should not be allowed to write to the model: " + res);
   199         } catch (IllegalStateException ex) {
   200             // OK, we can't read
   201         }
   202     }
   203 
   204     @Test public void computedPropertyCannotReadToModel() {
   205         leakedModel = model;
   206         try {
   207             String res = model.getNotAllowedRead();
   208             fail("We should not be allowed to read from the model: " + res);
   209         } catch (IllegalStateException ex) {
   210             // OK, we can't read
   211         }
   212     }
   213     
   214     @OnReceive(url = "{protocol}://{host}?query={query}", data = Person.class, onError = "errorState")
   215     static void loadPeople(Modelik thiz, People p) {
   216         Modelik m = null;
   217         m.applyBindings();
   218         m.loadPeople("http", "apidesign.org", "query", new Person());
   219     }
   220     
   221     static void errorState(Modelik thiz, Exception ex) {
   222         
   223     }
   224 
   225     @OnReceive(url = "{protocol}://{host}?callback={back}&query={query}", jsonp = "back")
   226     static void loadPeopleViaJSONP(Modelik thiz, People p) {
   227         Modelik m = null;
   228         m.applyBindings();
   229         m.loadPeopleViaJSONP("http", "apidesign.org", "query");
   230     }
   231     
   232     @Function 
   233     static void doSomething() {
   234     }
   235     
   236     @ComputedProperty
   237     static int powerValue(int value) {
   238         return value * value;
   239     }
   240     
   241     @OnPropertyChange({ "powerValue", "unrelated" })
   242     static void aPropertyChanged(Modelik m, String name) {
   243         m.setChangedProperty(name);
   244     }
   245 
   246     @OnPropertyChange({ "values" })
   247     static void anArrayPropertyChanged(String name, Modelik m) {
   248         m.setChangedProperty(name);
   249     }
   250     
   251     @Test public void changeAnything() {
   252         model.setCount(44);
   253         assertNull(model.getChangedProperty(), "No observed value change");
   254     }
   255     @Test public void changeValue() {
   256         model.setValue(33);
   257         assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
   258     }
   259     @Test public void changeUnrelated() {
   260         model.setUnrelated(333);
   261         assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
   262     }
   263 
   264     @Test public void changeInArray() {
   265         model.getValues().add(10);
   266         assertNull(model.getChangedProperty(), "No change before applyBindings");
   267         model.applyBindings();
   268         model.getValues().add(10);
   269         assertEquals(model.getChangedProperty(), "values", "Something added into the array");
   270     }
   271     
   272     @ComputedProperty
   273     static String notAllowedRead() {
   274         return "Not allowed callback: " + leakedModel.getUnrelated();
   275     }
   276 
   277     @ComputedProperty
   278     static String notAllowedWrite() {
   279         leakedModel.setUnrelated(11);
   280         return "Not allowed callback!";
   281     }
   282     
   283     @ComputedProperty
   284     static List<String> repeat(int count) {
   285         return Collections.nCopies(count, "Hello");
   286     }
   287     
   288     public @Test void hasPersonPropertyAndComputedFullName() {
   289         List<Person> arr = model.getPeople();
   290         assertEquals(arr.size(), 0, "By default empty");
   291         Person p = null;
   292         if (p != null) {
   293             String fullNameGenerated = p.getFullName();
   294             assertNotNull(fullNameGenerated);
   295         }
   296     }
   297     
   298     public @Test void computedListIsOfTypeString() {
   299         Person p = new Person("1st", "2nd", Sex.MALE);
   300         String first = p.getBothNames().get(0);
   301         String last = p.getBothNames().get(1);
   302         assertEquals(first, "1st");
   303         assertEquals(last, "2nd");
   304     }
   305     
   306     private static class MockTechnology implements Technology<Object> {
   307         private final List<String> mutated = new ArrayList<String>();
   308 
   309         @Override
   310         public Object wrapModel(Object model) {
   311             return this;
   312         }
   313 
   314         @Override
   315         public void valueHasMutated(Object data, String propertyName) {
   316             mutated.add(propertyName);
   317         }
   318 
   319         @Override
   320         public void bind(PropertyBinding b, Object model, Object data) {
   321         }
   322 
   323         @Override
   324         public void expose(FunctionBinding fb, Object model, Object d) {
   325         }
   326 
   327         @Override
   328         public void applyBindings(Object data) {
   329         }
   330 
   331         @Override
   332         public Object wrapArray(Object[] arr) {
   333             return arr;
   334         }
   335 
   336         @Override
   337         public <M> M toModel(Class<M> modelClass, Object data) {
   338             return modelClass.cast(data);
   339         }
   340 
   341         @Override
   342         public void runSafe(Runnable r) {
   343             throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   344         }
   345     }
   346 }