json/src/test/java/net/java/html/json/ModelTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Wed, 09 Dec 2015 23:59:56 +0100
changeset 1026 cda94194f901
parent 1017 10427ce1c0ee
parent 1025 1122c615fffd
permissions -rw-r--r--
Merge of #257086 into default branch
jtulach@0
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jtulach@0
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jtulach@0
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jtulach@0
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jtulach@0
    42
 */
jtulach@0
    43
package net.java.html.json;
jtulach@0
    44
jtulach@0
    45
import java.util.ArrayList;
jtulach@0
    46
import java.util.Collections;
jtulach@0
    47
import java.util.Iterator;
jtulach@0
    48
import java.util.List;
jtulach@0
    49
import java.util.ListIterator;
jtulach@938
    50
import net.java.html.BrwsrCtx;
jtulach@838
    51
import org.netbeans.html.context.spi.Contexts;
jtulach@838
    52
import org.netbeans.html.json.spi.FunctionBinding;
jtulach@838
    53
import org.netbeans.html.json.spi.PropertyBinding;
jtulach@838
    54
import org.netbeans.html.json.spi.Technology;
jtulach@938
    55
import static org.testng.Assert.assertEquals;
jtulach@938
    56
import static org.testng.Assert.assertFalse;
jtulach@938
    57
import static org.testng.Assert.assertNotNull;
jtulach@938
    58
import static org.testng.Assert.assertNull;
jtulach@938
    59
import static org.testng.Assert.assertTrue;
jtulach@938
    60
import static org.testng.Assert.fail;
jtulach@0
    61
import org.testng.annotations.BeforeMethod;
jtulach@0
    62
import org.testng.annotations.Test;
jtulach@0
    63
jtulach@0
    64
/**
jtulach@0
    65
 *
jtulach@790
    66
 * @author Jaroslav Tulach
jtulach@0
    67
 */
jtulach@1017
    68
@Model(className = "Modelik", builder = "change", targetId = "", properties = {
jtulach@0
    69
    @Property(name = "value", type = int.class),
jtulach@0
    70
    @Property(name = "count", type = int.class),
jtulach@0
    71
    @Property(name = "unrelated", type = long.class),
jtulach@0
    72
    @Property(name = "names", type = String.class, array = true),
jtulach@0
    73
    @Property(name = "values", type = int.class, array = true),
jtulach@0
    74
    @Property(name = "people", type = Person.class, array = true),
jtulach@0
    75
    @Property(name = "changedProperty", type=String.class)
jtulach@0
    76
})
jtulach@0
    77
public class ModelTest {
jaroslav@7
    78
    private MockTechnology my;
jtulach@0
    79
    private Modelik model;
jtulach@0
    80
    private static Modelik leakedModel;
jtulach@938
    81
jtulach@0
    82
    @BeforeMethod
jtulach@0
    83
    public void createModel() {
jaroslav@7
    84
        my = new MockTechnology();
jaroslav@111
    85
        final BrwsrCtx c = Contexts.newBuilder().register(Technology.class, my, 1).build();
jaroslav@111
    86
        model = Models.bind(new Modelik(), c);
jtulach@0
    87
    }
jtulach@938
    88
jtulach@0
    89
    @Test public void classGeneratedWithSetterGetter() {
jtulach@0
    90
        model.setValue(10);
jtulach@0
    91
        assertEquals(10, model.getValue(), "Value changed");
jtulach@0
    92
    }
jtulach@938
    93
jtulach@0
    94
    @Test public void computedMethod() {
jtulach@0
    95
        model.setValue(4);
jtulach@0
    96
        assertEquals(16, model.getPowerValue());
jtulach@0
    97
    }
jtulach@938
    98
jaroslav@281
    99
    @Test public void equalsAndHashCode() {
jtulach@1017
   100
        Modelik m1 = new Modelik();
jtulach@1017
   101
        m1.setValue(10);
jtulach@1017
   102
        m1.setCount(20);
jtulach@1017
   103
        m1.setUnrelated(30);
jtulach@1017
   104
        m1.setChangedProperty("changed");
jtulach@1017
   105
        m1.getNames().add("firstName");
jtulach@1017
   106
        Modelik m2 = new Modelik().
jtulach@1017
   107
            changeValue(10).
jtulach@1017
   108
            changeCount(20).
jtulach@1017
   109
            changeUnrelated(30).
jtulach@1017
   110
            changeChangedProperty("changed").
jtulach@1017
   111
            changeNames("firstName");
jtulach@938
   112
jaroslav@281
   113
        assertTrue(m1.equals(m2), "They are the same");
jaroslav@281
   114
        assertEquals(m1.hashCode(), m2.hashCode(), "Hashcode is the same");
jtulach@938
   115
jaroslav@281
   116
        m1.setCount(33);
jtulach@938
   117
jaroslav@281
   118
        assertFalse(m1.equals(m2), "No longer the same");
jaroslav@281
   119
        assertFalse(m1.hashCode() == m2.hashCode(), "No longe is hashcode is the same");
jaroslav@281
   120
    }
jtulach@938
   121
jtulach@0
   122
    @Test public void arrayIsMutable() {
jtulach@0
   123
        assertEquals(model.getNames().size(), 0, "Is empty");
jtulach@0
   124
        model.getNames().add("Jarda");
jtulach@0
   125
        assertEquals(model.getNames().size(), 1, "One element");
jtulach@0
   126
    }
jaroslav@6
   127
jaroslav@278
   128
    @Test public void arrayChangesNotNotifiedUntilInitied() {
jaroslav@278
   129
        model.getNames().add("Hello");
jaroslav@278
   130
        assertTrue(my.mutated.isEmpty(), "No change now " + my.mutated);
jaroslav@278
   131
        model.getNames().remove("Hello");
jaroslav@278
   132
        assertTrue(my.mutated.isEmpty(), "No change still " + my.mutated);
jaroslav@278
   133
        assertTrue(model.getNames().isEmpty(), "No empty");
jaroslav@278
   134
    }
jtulach@938
   135
jtulach@0
   136
    @Test public void arrayChangesNotified() {
jaroslav@453
   137
        Models.applyBindings(model);
jtulach@0
   138
        model.getNames().add("Hello");
jtulach@938
   139
jtulach@0
   140
        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
jtulach@0
   141
        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
jtulach@0
   142
jtulach@0
   143
        my.mutated.clear();
jtulach@938
   144
jtulach@0
   145
        Iterator<String> it = model.getNames().iterator();
jtulach@0
   146
        assertEquals(it.next(), "Hello");
jtulach@0
   147
        it.remove();
jtulach@938
   148
jtulach@0
   149
        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
jtulach@0
   150
        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
jtulach@0
   151
jtulach@0
   152
        my.mutated.clear();
jtulach@938
   153
jtulach@0
   154
        ListIterator<String> lit = model.getNames().listIterator();
jtulach@0
   155
        lit.add("Jarda");
jtulach@938
   156
jtulach@0
   157
        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
jtulach@0
   158
        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
jtulach@0
   159
    }
jaroslav@7
   160
jtulach@0
   161
    @Test public void autoboxedArray() {
jtulach@0
   162
        model.getValues().add(10);
jtulach@938
   163
jtulach@0
   164
        assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
jtulach@0
   165
    }
jtulach@0
   166
jtulach@0
   167
    @Test public void derivedArrayProp() {
jaroslav@280
   168
        model.applyBindings();
jtulach@0
   169
        model.setCount(10);
jtulach@938
   170
jtulach@0
   171
        List<String> arr = model.getRepeat();
jtulach@0
   172
        assertEquals(arr.size(), 10, "Ten items: " + arr);
jtulach@938
   173
jtulach@0
   174
        my.mutated.clear();
jtulach@938
   175
jtulach@0
   176
        model.setCount(5);
jtulach@938
   177
jtulach@0
   178
        arr = model.getRepeat();
jtulach@0
   179
        assertEquals(arr.size(), 5, "Five items: " + arr);
jtulach@0
   180
jtulach@0
   181
        assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
jtulach@0
   182
        assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
jtulach@0
   183
        assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
jtulach@0
   184
    }
jtulach@938
   185
jtulach@951
   186
    @Test public void derivedArrayPropChange() {
jtulach@951
   187
        model.applyBindings();
jtulach@951
   188
        model.setCount(5);
jtulach@951
   189
jtulach@951
   190
        List<String> arr = model.getRepeat();
jtulach@951
   191
        assertEquals(arr.size(), 5, "Five items: " + arr);
jtulach@951
   192
jtulach@951
   193
        model.setRepeat(10);
jtulach@951
   194
        assertEquals(model.getCount(), 10, "Changing repeat changes count");
jtulach@951
   195
    }
jtulach@951
   196
jtulach@0
   197
    @Test public void derivedPropertiesAreNotified() {
jaroslav@280
   198
        model.applyBindings();
jtulach@938
   199
jtulach@0
   200
        model.setValue(33);
jtulach@938
   201
jtulach@0
   202
        // not interested in change of this property
jtulach@0
   203
        my.mutated.remove("changedProperty");
jtulach@938
   204
jtulach@0
   205
        assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
jtulach@0
   206
        assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
jtulach@0
   207
        assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
jtulach@938
   208
jtulach@0
   209
        my.mutated.clear();
jtulach@938
   210
jtulach@0
   211
        model.setUnrelated(44);
jtulach@938
   212
jtulach@938
   213
jtulach@0
   214
        // not interested in change of this property
jtulach@0
   215
        my.mutated.remove("changedProperty");
jtulach@0
   216
        assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
jtulach@0
   217
        assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
jtulach@0
   218
    }
jaroslav@8
   219
jtulach@0
   220
    @Test public void computedPropertyCannotWriteToModel() {
jtulach@0
   221
        leakedModel = model;
jtulach@0
   222
        try {
jtulach@0
   223
            String res = model.getNotAllowedWrite();
jtulach@0
   224
            fail("We should not be allowed to write to the model: " + res);
jtulach@0
   225
        } catch (IllegalStateException ex) {
jtulach@0
   226
            // OK, we can't read
jtulach@0
   227
        }
jtulach@0
   228
    }
jtulach@0
   229
jtulach@0
   230
    @Test public void computedPropertyCannotReadToModel() {
jtulach@0
   231
        leakedModel = model;
jtulach@0
   232
        try {
jtulach@0
   233
            String res = model.getNotAllowedRead();
jtulach@0
   234
            fail("We should not be allowed to read from the model: " + res);
jtulach@0
   235
        } catch (IllegalStateException ex) {
jtulach@0
   236
            // OK, we can't read
jtulach@0
   237
        }
jtulach@0
   238
    }
jtulach@938
   239
jaroslav@245
   240
    @OnReceive(url = "{protocol}://{host}?query={query}", data = Person.class, onError = "errorState")
jaroslav@13
   241
    static void loadPeople(Modelik thiz, People p) {
jaroslav@12
   242
        Modelik m = null;
jaroslav@14
   243
        m.applyBindings();
jaroslav@111
   244
        m.loadPeople("http", "apidesign.org", "query", new Person());
jaroslav@12
   245
    }
jtulach@938
   246
jaroslav@245
   247
    static void errorState(Modelik thiz, Exception ex) {
jtulach@938
   248
jaroslav@245
   249
    }
jaroslav@24
   250
jtulach@940
   251
    @OnReceive(url="{url}", headers={
jtulach@940
   252
        "Easy: {easy}",
jtulach@940
   253
        "H-a+r!d?e.r: {harder}",
jtulach@940
   254
        "H-a+r!d?e's\"t: {harder}",
jtulach@940
   255
        "Repeat-ed: {rep}",
jtulach@940
   256
        "Repeat+ed: {rep}",
jtulach@940
   257
        "Same-URL: {url}"
jtulach@940
   258
    })
jtulach@940
   259
    static void fetchPeopleWithHeaders(Modelik model, People p) {
jtulach@940
   260
        model.fetchPeopleWithHeaders("url", "easy", "harder", "rep");
jtulach@940
   261
    }
jtulach@940
   262
jaroslav@24
   263
    @OnReceive(url = "{protocol}://{host}?callback={back}&query={query}", jsonp = "back")
jaroslav@24
   264
    static void loadPeopleViaJSONP(Modelik thiz, People p) {
jaroslav@24
   265
        Modelik m = null;
jaroslav@24
   266
        m.applyBindings();
jaroslav@24
   267
        m.loadPeopleViaJSONP("http", "apidesign.org", "query");
jaroslav@24
   268
    }
jtulach@938
   269
jtulach@938
   270
    @OnReceive(url = "{rep}://{rep}")
jtulach@938
   271
    static void repeatedTest(Modelik thiz, People p) {
jtulach@938
   272
        thiz.repeatedTest("justOneParameterRep");
jtulach@938
   273
    }
jtulach@938
   274
jtulach@938
   275
    @Function
jtulach@0
   276
    static void doSomething() {
jtulach@0
   277
    }
jtulach@938
   278
jtulach@951
   279
    @ComputedProperty(write = "setPowerValue")
jtulach@0
   280
    static int powerValue(int value) {
jtulach@0
   281
        return value * value;
jtulach@0
   282
    }
jtulach@938
   283
jtulach@951
   284
    static void setPowerValue(Modelik m, int value) {
jtulach@951
   285
        m.setValue((int)Math.sqrt(value));
jtulach@951
   286
    }
jtulach@951
   287
jtulach@0
   288
    @OnPropertyChange({ "powerValue", "unrelated" })
jtulach@0
   289
    static void aPropertyChanged(Modelik m, String name) {
jtulach@0
   290
        m.setChangedProperty(name);
jtulach@0
   291
    }
jtulach@0
   292
jtulach@0
   293
    @OnPropertyChange({ "values" })
jtulach@0
   294
    static void anArrayPropertyChanged(String name, Modelik m) {
jtulach@0
   295
        m.setChangedProperty(name);
jtulach@0
   296
    }
jtulach@938
   297
jtulach@0
   298
    @Test public void changeAnything() {
jtulach@0
   299
        model.setCount(44);
jtulach@0
   300
        assertNull(model.getChangedProperty(), "No observed value change");
jtulach@0
   301
    }
jtulach@0
   302
    @Test public void changeValue() {
jtulach@0
   303
        model.setValue(33);
jtulach@0
   304
        assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
jtulach@0
   305
    }
jtulach@951
   306
    @Test public void changePowerValue() {
jtulach@951
   307
        model.setValue(3);
jtulach@951
   308
        assertEquals(model.getPowerValue(), 9, "Square");
jtulach@951
   309
        model.setPowerValue(16);
jtulach@951
   310
        assertEquals(model.getValue(), 4, "Square root");
jtulach@951
   311
        assertEquals(model.getPowerValue(), 16, "Square changed");
jtulach@951
   312
    }
jtulach@0
   313
    @Test public void changeUnrelated() {
jtulach@0
   314
        model.setUnrelated(333);
jtulach@0
   315
        assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
jtulach@0
   316
    }
jtulach@0
   317
jtulach@0
   318
    @Test public void changeInArray() {
jtulach@0
   319
        model.getValues().add(10);
jaroslav@278
   320
        assertNull(model.getChangedProperty(), "No change before applyBindings");
jaroslav@278
   321
        model.applyBindings();
jaroslav@278
   322
        model.getValues().add(10);
jtulach@0
   323
        assertEquals(model.getChangedProperty(), "values", "Something added into the array");
jtulach@0
   324
    }
jtulach@938
   325
jtulach@0
   326
    @ComputedProperty
jtulach@0
   327
    static String notAllowedRead() {
jtulach@0
   328
        return "Not allowed callback: " + leakedModel.getUnrelated();
jtulach@0
   329
    }
jtulach@0
   330
jtulach@0
   331
    @ComputedProperty
jtulach@0
   332
    static String notAllowedWrite() {
jtulach@0
   333
        leakedModel.setUnrelated(11);
jtulach@0
   334
        return "Not allowed callback!";
jtulach@0
   335
    }
jtulach@938
   336
jtulach@951
   337
    @ComputedProperty(write="parseRepeat")
jtulach@0
   338
    static List<String> repeat(int count) {
jtulach@0
   339
        return Collections.nCopies(count, "Hello");
jtulach@0
   340
    }
jtulach@951
   341
    static void parseRepeat(Modelik m, Object v) {
jtulach@951
   342
        m.setCount((Integer)v);
jtulach@951
   343
    }
jtulach@938
   344
jtulach@0
   345
    public @Test void hasPersonPropertyAndComputedFullName() {
jtulach@0
   346
        List<Person> arr = model.getPeople();
jtulach@0
   347
        assertEquals(arr.size(), 0, "By default empty");
jtulach@0
   348
        Person p = null;
jtulach@0
   349
        if (p != null) {
jtulach@0
   350
            String fullNameGenerated = p.getFullName();
jtulach@0
   351
            assertNotNull(fullNameGenerated);
jtulach@0
   352
        }
jtulach@0
   353
    }
jtulach@938
   354
jaroslav@562
   355
    public @Test void computedListIsOfTypeString() {
jaroslav@562
   356
        Person p = new Person("1st", "2nd", Sex.MALE);
jaroslav@562
   357
        String first = p.getBothNames().get(0);
jaroslav@562
   358
        String last = p.getBothNames().get(1);
jaroslav@562
   359
        assertEquals(first, "1st");
jaroslav@562
   360
        assertEquals(last, "2nd");
jaroslav@562
   361
    }
jtulach@1025
   362
    
jtulach@1025
   363
    @Model(className = "Inner", properties = {
jtulach@1025
   364
        @Property(name = "x", type = int.class)
jtulach@1025
   365
    })
jtulach@1025
   366
    static final class InnerCntrl {
jtulach@1025
   367
        @OnPropertyChange("x")
jtulach@1025
   368
        static void increment(Inner model) {
jtulach@1025
   369
            model.setX(model.getX() + 1);
jtulach@1025
   370
        }
jtulach@1025
   371
    }
jtulach@938
   372
jaroslav@7
   373
    private static class MockTechnology implements Technology<Object> {
jaroslav@100
   374
        private final List<String> mutated = new ArrayList<String>();
jaroslav@7
   375
jaroslav@7
   376
        @Override
jaroslav@7
   377
        public Object wrapModel(Object model) {
jaroslav@7
   378
            return this;
jaroslav@7
   379
        }
jaroslav@7
   380
jaroslav@7
   381
        @Override
jaroslav@7
   382
        public void valueHasMutated(Object data, String propertyName) {
jaroslav@7
   383
            mutated.add(propertyName);
jaroslav@7
   384
        }
jaroslav@9
   385
jaroslav@9
   386
        @Override
jaroslav@9
   387
        public void bind(PropertyBinding b, Object model, Object data) {
jaroslav@9
   388
        }
jaroslav@11
   389
jaroslav@11
   390
        @Override
jaroslav@11
   391
        public void expose(FunctionBinding fb, Object model, Object d) {
jaroslav@11
   392
        }
jaroslav@14
   393
jaroslav@14
   394
        @Override
jaroslav@14
   395
        public void applyBindings(Object data) {
jaroslav@14
   396
        }
jaroslav@17
   397
jaroslav@17
   398
        @Override
jaroslav@17
   399
        public Object wrapArray(Object[] arr) {
jaroslav@17
   400
            return arr;
jaroslav@17
   401
        }
jaroslav@38
   402
jaroslav@38
   403
        @Override
jaroslav@38
   404
        public <M> M toModel(Class<M> modelClass, Object data) {
jaroslav@38
   405
            return modelClass.cast(data);
jaroslav@38
   406
        }
jaroslav@240
   407
jaroslav@240
   408
        @Override
jaroslav@240
   409
        public void runSafe(Runnable r) {
jaroslav@240
   410
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
jaroslav@240
   411
        }
jaroslav@7
   412
    }
jtulach@0
   413
}