1d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar/* 2d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Copyright (C) 2015 The Android Open Source Project 3d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 4d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * you may not use this file except in compliance with the License. 6d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * You may obtain a copy of the License at 7d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 8d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * 10d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * See the License for the specific language governing permissions and 14d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar * limitations under the License. 15d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar */ 16d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.expr; 18d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 19d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mountimport android.databinding.Bindable; 20e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyarimport android.databinding.Observable; 21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.LayoutBinder; 22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.MockLayoutBinder; 23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer; 24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass; 25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.java.JavaAnalyzer; 26c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport android.databinding.tool.store.Location; 27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.L; 28e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mountimport android.databinding.tool.writer.KCode; 29fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount 30d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.Before; 31d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.Rule; 32d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.Test; 33d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.rules.TestWatcher; 34d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.runner.Description; 35d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 3674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyarimport java.util.ArrayList; 3774f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyarimport java.util.Arrays; 38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet; 397b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyarimport java.util.Collections; 40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List; 41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 42fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport static org.junit.Assert.assertEquals; 43fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport static org.junit.Assert.assertFalse; 44fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport static org.junit.Assert.assertNotNull; 45fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport static org.junit.Assert.assertNull; 46fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport static org.junit.Assert.assertSame; 47fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport static org.junit.Assert.assertTrue; 48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class ExprModelTest { 5074f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private static class DummyExpr extends Expr { 5274f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar String mKey; 5474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public DummyExpr(String key, DummyExpr... children) { 56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar super(children); 57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mKey = key; 58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 59d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 60d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 6197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) { 6297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar return modelAnalyzer.findClass(Integer.class); 63d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 64d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 65d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 66d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected List<Dependency> constructDependencies() { 67d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return constructDynamicChildrenDependencies(); 68d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected String computeUniqueKey() { 72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return mKey + super.computeUniqueKey(); 73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 74e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount 75e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount @Override 76d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount protected KCode generateCode(boolean full) { 77e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount return new KCode(); 78e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount } 79d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount 80d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount @Override 81d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount protected String getInvertibleError() { 82d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount return "DummyExpr cannot be 2-way."; 83d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount } 84d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar ExprModel mExprModel; 87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Rule 89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public TestWatcher mTestWatcher = new TestWatcher() { 90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Override 91d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar protected void failed(Throwable e, Description description) { 92d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar if (mExprModel != null && mExprModel.getFlagMapping() != null) { 93d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final String[] mapping = mExprModel.getFlagMapping(); 9474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar for (int i = 0; i < mapping.length; i++) { 95d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar L.d("flag %d: %s", i, mapping[i]); 96d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 97d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 98d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 99d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar }; 100d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Before 102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void setUp() throws Exception { 10397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar JavaAnalyzer.initForTests(); 104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = new ExprModel(); 105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 107d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 108d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testAddNormal() { 109d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final DummyExpr d = new DummyExpr("a"); 110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertSame(d, mExprModel.register(d)); 111d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertSame(d, mExprModel.register(d)); 112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(1, mExprModel.mExprMap.size()); 113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 11474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 115d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 116d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testAddDupe1() { 117d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final DummyExpr d = new DummyExpr("a"); 118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertSame(d, mExprModel.register(d)); 119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertSame(d, mExprModel.register(new DummyExpr("a"))); 120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(1, mExprModel.mExprMap.size()); 121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 122d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 123d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 124d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testAddMultiple() { 125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.register(new DummyExpr("a")); 126d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.register(new DummyExpr("b")); 127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(2, mExprModel.mExprMap.size()); 128d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 129d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 130d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testAddWithChildren() { 133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar DummyExpr a = new DummyExpr("a"); 134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar DummyExpr b = new DummyExpr("b"); 135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar DummyExpr c = new DummyExpr("c", a, b); 136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.register(c); 137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar DummyExpr a2 = new DummyExpr("a"); 138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar DummyExpr b2 = new DummyExpr("b"); 139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar DummyExpr c2 = new DummyExpr("c", a, b); 140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(c, mExprModel.register(c2)); 141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testShouldRead() { 145eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = lb.getModel(); 147c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", "java.lang.String", null); 148c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", "java.lang.String", null); 149c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", "java.lang.String", null); 150d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount lb.parse("a == null ? b : c", false, null); 15174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class)); 152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar lb.getModel().seal(); 1532611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // a and a == null 1552611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, shouldRead.size()); 1562611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar final List<Expr> readFirst = getReadFirst(shouldRead, null); 1572611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, readFirst.size()); 1582611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar final Expr first = readFirst.get(0); 159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertSame(a, first); 160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // now , assume we've read this 161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final BitSet shouldReadFlags = first.getShouldReadFlags(); 162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertNotNull(shouldReadFlags); 163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 16609aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar public void testReadConstantTernary() { 16709aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 16809aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar mExprModel = lb.getModel(); 16909aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar IdentifierExpr a = lb.addVariable("a", "java.lang.String", null); 17009aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar IdentifierExpr b = lb.addVariable("b", "java.lang.String", null); 17109aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar TernaryExpr ternaryExpr = parse(lb, "true ? a : b", TernaryExpr.class); 17209aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar mExprModel.seal(); 17309aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar List<Expr> shouldRead = getShouldRead(); 17409aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar assertExactMatch(shouldRead, ternaryExpr.getPred()); 17509aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar List<Expr> first = getReadFirst(shouldRead); 17609aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar assertExactMatch(first, ternaryExpr.getPred()); 17709aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar mExprModel.markBitsRead(); 17809aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar shouldRead = getShouldRead(); 17909aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar assertExactMatch(shouldRead, a, b, ternaryExpr); 18009aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar first = getReadFirst(shouldRead); 18109aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar assertExactMatch(first, a, b); 1829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar List<Expr> justRead = new ArrayList<Expr>(); 18309aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar justRead.add(a); 18409aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar justRead.add(b); 18509aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar first = filterOut(getReadFirst(shouldRead, justRead), justRead); 18609aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar assertExactMatch(first, ternaryExpr); 18709aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar assertFalse(mExprModel.markBitsRead()); 18809aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar } 18909aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar 19009aeb26073fc8a98263806f53e44819ebe5046c6Yigit Boyar @Test 19174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar public void testTernaryWithPlus() { 192eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 19374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar mExprModel = lb.getModel(); 19474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar IdentifierExpr user = lb 195c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar .addVariable("user", "android.databinding.tool.expr.ExprModelTest.User", 196c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 19774f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar MathExpr parsed = parse(lb, "user.name + \" \" + (user.lastName ?? \"\")", MathExpr.class); 19874f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar mExprModel.seal(); 1992611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> toRead = getShouldRead(); 2002611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> readNow = getReadFirst(toRead); 2012611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, readNow.size()); 2022611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertSame(user, readNow.get(0)); 20374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar List<Expr> justRead = new ArrayList<Expr>(); 20474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar justRead.add(user); 20574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar readNow = filterOut(getReadFirst(toRead, justRead), justRead); 2062611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, readNow.size()); //user.name && user.lastName 2072611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar justRead.addAll(readNow); 20874f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar // user.lastname (T, F), user.name + " " 20974f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar readNow = filterOut(getReadFirst(toRead, justRead), justRead); 2102611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, readNow.size()); //user.name && user.lastName 2112611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar justRead.addAll(readNow); 21274f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar readNow = filterOut(getReadFirst(toRead, justRead), justRead); 2132611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, readNow.size()); 21474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar mExprModel.markBitsRead(); 21574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 21674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar toRead = getShouldRead(); 2172611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, toRead.size()); 21874f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar justRead.clear(); 21974f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar readNow = filterOut(getReadFirst(toRead, justRead), justRead); 2202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, readNow.size()); 2212611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertSame(parsed.getRight(), readNow.get(0)); 2222611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar justRead.addAll(readNow); 22374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 22474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar readNow = filterOut(getReadFirst(toRead, justRead), justRead); 2252611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, readNow.size()); 2262611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertSame(parsed, readNow.get(0)); 2272611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar justRead.addAll(readNow); 22874f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 22974f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar readNow = filterOut(getReadFirst(toRead, justRead), justRead); 2302611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, readNow.size()); 23174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar mExprModel.markBitsRead(); 2322611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 23374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar } 23474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 2352611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private List<Expr> filterOut(List<Expr> itr, final List<Expr> exclude) { 2362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> result = new ArrayList<Expr>(); 2372611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr expr : itr) { 2382611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (!exclude.contains(expr)) { 2392611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.add(expr); 24074f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar } 2412611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 2422611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result; 24374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar } 24474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 24574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar @Test 2460fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar public void testTernaryInsideTernary() { 247eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 2480fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar mExprModel = lb.getModel(); 249c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr cond1 = lb.addVariable("cond1", "boolean", null); 250c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr cond2 = lb.addVariable("cond2", "boolean", null); 2510fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 252c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", "boolean", null); 253c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", "boolean", null); 254c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", "boolean", null); 2550fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2560fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar final TernaryExpr ternaryExpr = parse(lb, "cond1 ? cond2 ? a : b : c", TernaryExpr.class); 2570fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar final TernaryExpr innerTernary = (TernaryExpr) ternaryExpr.getIfTrue(); 2580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar mExprModel.seal(); 2590fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2602611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> toRead = getShouldRead(); 2612611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, toRead.size()); 2622611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(ternaryExpr.getPred(), toRead.get(0)); 2630fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2642611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> readNow = getReadFirst(toRead); 2652611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, readNow.size()); 2662611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(ternaryExpr.getPred(), readNow.get(0)); 2670fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar int cond1True = ternaryExpr.getRequirementFlagIndex(true); 2680fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar int cond1False = ternaryExpr.getRequirementFlagIndex(false); 2690fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar // ok, it is read now. 2700fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar mExprModel.markBitsRead(); 2710fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2720fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar // now it should read cond2 or c, depending on the flag from first 2730fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar toRead = getShouldRead(); 2742611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, toRead.size()); 2750fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertExactMatch(toRead, ternaryExpr.getIfFalse(), innerTernary.getPred()); 2760fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertFlags(ternaryExpr.getIfFalse(), cond1False); 2770fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertFlags(ternaryExpr.getIfTrue(), cond1True); 2780fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2790fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar mExprModel.markBitsRead(); 2800fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2810fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar // now it should read a or b, innerTernary, outerTernary 2820fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar toRead = getShouldRead(); 2830fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertExactMatch(toRead, innerTernary.getIfTrue(), innerTernary.getIfFalse(), ternaryExpr, 2840fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar innerTernary); 2850fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertFlags(innerTernary.getIfTrue(), innerTernary.getRequirementFlagIndex(true)); 2860fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertFlags(innerTernary.getIfFalse(), innerTernary.getRequirementFlagIndex(false)); 2870fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar assertFalse(mExprModel.markBitsRead()); 2880fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar } 2890fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar 2900fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar @Test 291d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testRequirementFlags() { 292eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 293d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = lb.getModel(); 294c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", "java.lang.String", null); 295c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", "java.lang.String", null); 296c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", "java.lang.String", null); 297c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr d = lb.addVariable("d", "java.lang.String", null); 298c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr e = lb.addVariable("e", "java.lang.String", null); 299d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e", false, null); 300d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(aTernary instanceof TernaryExpr); 30174f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar final Expr bTernary = ((TernaryExpr) aTernary).getIfTrue(); 302d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(bTernary instanceof TernaryExpr); 30374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar final Expr aIsNull = mExprModel 30474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar .comparison("==", a, mExprModel.symbol("null", Object.class)); 30574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar final Expr bIsNull = mExprModel 30674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar .comparison("==", b, mExprModel.symbol("null", Object.class)); 307d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar lb.getModel().seal(); 3082611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 309d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // a and a == null 3102611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, shouldRead.size()); 311d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFalse(a.getShouldReadFlags().isEmpty()); 312d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(a.getShouldReadFlags().get(a.getId())); 313d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(b.getShouldReadFlags().isEmpty()); 314d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(c.getShouldReadFlags().isEmpty()); 315d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(d.getShouldReadFlags().isEmpty()); 316d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(e.getShouldReadFlags().isEmpty()); 317d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 3182611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> readFirst = getReadFirst(shouldRead, null); 3192611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(1, readFirst.size()); 3202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar final Expr first = readFirst.get(0); 321d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertSame(a, first); 322d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(mExprModel.markBitsRead()); 323d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : mExprModel.getPendingExpressions()) { 324d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertNull(expr.mShouldReadFlags); 325d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 3260fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar shouldRead = getShouldRead(); 327d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, e, b, bIsNull); 328d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 329d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(e, aTernary.getRequirementFlagIndex(false)); 330d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 331d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(b, aTernary.getRequirementFlagIndex(true)); 332d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(bIsNull, aTernary.getRequirementFlagIndex(true)); 333d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(mExprModel.markBitsRead()); 3340fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar shouldRead = getShouldRead(); 3352611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(4, shouldRead.size()); 3362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertTrue(shouldRead.contains(c)); 3372611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertTrue(shouldRead.contains(d)); 3382611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertTrue(shouldRead.contains(aTernary)); 3392611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertTrue(shouldRead.contains(bTernary)); 340d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 341d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(c.getShouldReadFlags().get(bTernary.getRequirementFlagIndex(true))); 342d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(1, c.getShouldReadFlags().cardinality()); 343d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 344d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(d.getShouldReadFlags().get(bTernary.getRequirementFlagIndex(false))); 345d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(1, d.getShouldReadFlags().cardinality()); 346d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 347d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(bTernary.getShouldReadFlags().get(aTernary.getRequirementFlagIndex(true))); 348d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals(1, bTernary.getShouldReadFlags().cardinality()); 349019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 350019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertEquals(6, aTernary.getShouldReadFlags().cardinality()); 351d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : new Expr[]{a, b, c, d, e}) { 352d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(aTernary.getShouldReadFlags().get(expr.getId())); 353d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 354d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 355d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar readFirst = getReadFirst(shouldRead); 3562611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(2, readFirst.size()); 3572611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertTrue(readFirst.contains(c)); 3582611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertTrue(readFirst.contains(d)); 359d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFalse(mExprModel.markBitsRead()); 360d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 361d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 362d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 363d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testPostConditionalDependencies() { 364eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 365d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = lb.getModel(); 366d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 367c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr u1 = lb.addVariable("u1", User.class.getCanonicalName(), null); 368c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr u2 = lb.addVariable("u2", User.class.getCanonicalName(), null); 369c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName(), null); 370c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName(), null); 371c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", int.class.getCanonicalName(), null); 372c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr d = lb.addVariable("d", int.class.getCanonicalName(), null); 373c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr e = lb.addVariable("e", int.class.getCanonicalName(), null); 374d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar TernaryExpr abTernary = parse(lb, "a > b ? u1.name : u2.name", TernaryExpr.class); 37574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar TernaryExpr bcTernary = parse(lb, "b > c ? u1.getCond(d) ? u1.lastName : u2.lastName : `xx`" 37674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar + " + u2.getCond(e) ", TernaryExpr.class); 377d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr abCmp = abTernary.getPred(); 378d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr bcCmp = bcTernary.getPred(); 379d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr u1GetCondD = ((TernaryExpr) bcTernary.getIfTrue()).getPred(); 380d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final MathExpr xxPlusU2getCondE = (MathExpr) bcTernary.getIfFalse(); 38197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar Expr u2GetCondE = xxPlusU2getCondE.getRight(); 382d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr u1Name = abTernary.getIfTrue(); 383d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr u2Name = abTernary.getIfFalse(); 384d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr u1LastName = ((TernaryExpr) bcTernary.getIfTrue()).getIfTrue(); 385d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr u2LastName = ((TernaryExpr) bcTernary.getIfTrue()).getIfFalse(); 386d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 387d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.seal(); 3882611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 389d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 390d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, a, b, c, abCmp, bcCmp); 391d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 3922611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> firstRead = getReadFirst(shouldRead); 393d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 394d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(firstRead, a, b, c); 395d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 396d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(a, a, b, u1, u2, u1Name, u2Name); 397d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(b, a, b, u1, u2, u1Name, u2Name, c, d, u1LastName, u2LastName, e); 398d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(c, b, c, u1, d, u1LastName, u2LastName, e); 399d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(abCmp, a, b, u1, u2, u1Name, u2Name); 400d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(bcCmp, b, c, u1, d, u1LastName, u2LastName, e); 401d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 402d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(mExprModel.markBitsRead()); 403d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 4040fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar shouldRead = getShouldRead(); 405d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar Expr[] batch = {d, e, u1, u2, u1GetCondD, u2GetCondE, xxPlusU2getCondE, abTernary, 406d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar abTernary.getIfTrue(), abTernary.getIfFalse()}; 407d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, batch); 408d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar firstRead = getReadFirst(shouldRead); 409d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(firstRead, d, e, u1, u2); 410d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 411d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(d, bcTernary.getRequirementFlagIndex(true)); 412d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(e, bcTernary.getRequirementFlagIndex(false)); 41374f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar assertFlags(u1, bcTernary.getRequirementFlagIndex(true), 41474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar abTernary.getRequirementFlagIndex(true)); 41574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar assertFlags(u2, bcTernary.getRequirementFlagIndex(false), 41674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar abTernary.getRequirementFlagIndex(false)); 417d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 418d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(u1GetCondD, bcTernary.getRequirementFlagIndex(true)); 419d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(u2GetCondE, bcTernary.getRequirementFlagIndex(false)); 420d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(xxPlusU2getCondE, bcTernary.getRequirementFlagIndex(false)); 421d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(abTernary, a, b, u1, u2, u1Name, u2Name); 422d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(abTernary.getIfTrue(), abTernary.getRequirementFlagIndex(true)); 423d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(abTernary.getIfFalse(), abTernary.getRequirementFlagIndex(false)); 424d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 425d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(mExprModel.markBitsRead()); 426d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 4270fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar shouldRead = getShouldRead(); 428eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // FIXME: there is no real case to read u1 anymore because if b>c was not true, 429d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // u1.getCond(d) will never be set. Right now, we don't have mechanism to figure this out 430d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar // and also it does not affect correctness (just an unnecessary if stmt) 431d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount assertExactMatch(shouldRead, u1, u2, u1LastName, u2LastName, bcTernary.getIfTrue(), bcTernary); 432d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar firstRead = getReadFirst(shouldRead); 433d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount assertExactMatch(firstRead, u1, u2); 434eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFlags(u1, bcTernary.getIfTrue().getRequirementFlagIndex(true)); 435eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFlags(u2, bcTernary.getIfTrue().getRequirementFlagIndex(false)); 436d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(u1LastName, bcTernary.getIfTrue().getRequirementFlagIndex(true)); 437d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(u2LastName, bcTernary.getIfTrue().getRequirementFlagIndex(false)); 438d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 439d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(bcTernary.getIfTrue(), bcTernary.getRequirementFlagIndex(true)); 440d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(bcTernary, b, c, u1, u2, d, u1LastName, u2LastName, e); 441eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 442eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFalse(mExprModel.markBitsRead()); 443d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 444d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 445d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 446d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testCircularDependency() { 447eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 448d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = lb.getModel(); 449c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName(), 450c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 451c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName(), 452c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 453d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final TernaryExpr abTernary = parse(lb, "a > 3 ? a : b", TernaryExpr.class); 454d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.seal(); 4552611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 456d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, a, abTernary.getPred()); 457d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(mExprModel.markBitsRead()); 4580fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar shouldRead = getShouldRead(); 459d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, b, abTernary); 460d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFalse(mExprModel.markBitsRead()); 461d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 462d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 463d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 464d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public void testNestedCircularDependency() { 465eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 466d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel = lb.getModel(); 467c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName(), 468c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 469c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName(), 470c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 471c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", int.class.getCanonicalName(), 472c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 473d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final TernaryExpr a3Ternary = parse(lb, "a > 3 ? c > 4 ? a : b : c", TernaryExpr.class); 474d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar final TernaryExpr c4Ternary = (TernaryExpr) a3Ternary.getIfTrue(); 475d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar mExprModel.seal(); 4762611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 477d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, a, a3Ternary.getPred()); 478d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(mExprModel.markBitsRead()); 4790fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar shouldRead = getShouldRead(); 480d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertExactMatch(shouldRead, c, c4Ternary.getPred()); 481d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(c, a3Ternary.getRequirementFlagIndex(true), 482d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar a3Ternary.getRequirementFlagIndex(false)); 483d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertFlags(c4Ternary.getPred(), a3Ternary.getRequirementFlagIndex(true)); 484d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 485d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 486d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar @Test 487d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount public void testInterExprDependency() { 488eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 489d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount mExprModel = lb.getModel(); 490d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount IdentifierExpr u = lb.addVariable("u", User.class.getCanonicalName(), 491d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount null); 492d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount final Expr uComment = parse(lb, "u.comment", FieldAccessExpr.class); 493876ba3272f17ed891ea455e7dd526d44e468757cYigit Boyar final TernaryExpr uTernary = parse(lb, "u.getUseComment ? u.comment : `xx`", TernaryExpr.class); 494d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount mExprModel.seal(); 495eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertTrue(uTernary.getPred().canBeInvalidated()); 496d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount List<Expr> shouldRead = getShouldRead(); 497d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount assertExactMatch(shouldRead, u, uComment, uTernary.getPred()); 498d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount assertTrue(mExprModel.markBitsRead()); 499d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount shouldRead = getShouldRead(); 500eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, uComment, uTernary); 501d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount } 502d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount 503d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount @Test 5048533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar public void testInterExprCircularDependency() { 505eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 5068533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar mExprModel = lb.getModel(); 507c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", int.class.getCanonicalName(), 508c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 509c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", int.class.getCanonicalName(), 510c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 5118533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar final TernaryExpr abTernary = parse(lb, "a > 3 ? a : b", TernaryExpr.class); 5128533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar final TernaryExpr abTernary2 = parse(lb, "b > 3 ? b : a", TernaryExpr.class); 5138533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar mExprModel.seal(); 5142611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 5158533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar assertExactMatch(shouldRead, a, b, abTernary.getPred(), abTernary2.getPred()); 5168533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar assertTrue(mExprModel.markBitsRead()); 5178533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar shouldRead = getShouldRead(); 5188533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar assertExactMatch(shouldRead, abTernary, abTernary2); 5198533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar } 5208533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar 5218533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar @Test 5227b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar public void testInterExprCircularDependency2() { 523eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 5247b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel = lb.getModel(); 525c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", boolean.class.getCanonicalName(), 526c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 527c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", boolean.class.getCanonicalName(), 528c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 5297b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr abTernary = parse(lb, "a ? b : true", TernaryExpr.class); 5307b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr baTernary = parse(lb, "b ? a : false", TernaryExpr.class); 5317b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel.seal(); 5322611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 5337b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(shouldRead, a, b); 534eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFlags(a, a, b); 535eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFlags(b, a, b); 5362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> readFirst = getReadFirst(shouldRead); 5377b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(readFirst, a, b); 5387b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertTrue(mExprModel.markBitsRead()); 5397b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 540eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, abTernary, baTernary); 5417b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar readFirst = getReadFirst(shouldRead); 5427b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(readFirst, abTernary, baTernary); 5437b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertFalse(mExprModel.markBitsRead()); 5447b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 5452611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, shouldRead.size()); 5467b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 5477b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 5487b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar @Test 5497b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar public void testInterExprCircularDependency3() { 550eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 5517b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel = lb.getModel(); 552c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", boolean.class.getCanonicalName(), 553c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 554c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", boolean.class.getCanonicalName(), 555c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 556c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", boolean.class.getCanonicalName(), 557c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 5587b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr abTernary = parse(lb, "a ? b : c", TernaryExpr.class); 5597b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr abTernary2 = parse(lb, "b ? a : c", TernaryExpr.class); 5607b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel.seal(); 5612611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 5627b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(shouldRead, a, b); 5637b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertTrue(mExprModel.markBitsRead()); 5647b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 5657b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar // read a and b again, this time for their dependencies and also the rest since everything 5667b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar // is ready to be read 567eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, c, abTernary, abTernary2); 5687b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel.markBitsRead(); 5697b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 5702611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, shouldRead.size()); 5717b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 5727b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 5737b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar @Test 5747b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar public void testInterExprCircularDependency4() { 575eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 5767b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel = lb.getModel(); 577c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", boolean.class.getCanonicalName(), 578c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 579c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", boolean.class.getCanonicalName(), 580c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 581c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", boolean.class.getCanonicalName(), 582c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 583c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr d = lb.addVariable("d", boolean.class.getCanonicalName(), 584c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 5857b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr cTernary = parse(lb, "c ? (a ? d : false) : false", TernaryExpr.class); 5867b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr abTernary = parse(lb, "a ? b : true", TernaryExpr.class); 5877b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr baTernary = parse(lb, "b ? a : false", TernaryExpr.class); 5887b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel.seal(); 5892611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 590eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // check if a,b or c should be read. these are easily calculated from binding expressions' 591eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // invalidation 5927b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(shouldRead, c, a, b); 5937b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 5947b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar List<Expr> justRead = new ArrayList<Expr>(); 5952611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> readFirst = getReadFirst(shouldRead); 5967b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(readFirst, c, a, b); 5977b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar Collections.addAll(justRead, a, b, c); 5982611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, filterOut(getReadFirst(shouldRead, justRead), justRead).size()); 5997b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertTrue(mExprModel.markBitsRead()); 6007b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 601eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // if a and b are not invalid, a won't be read in the first step. But if c's expression 602eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // is invalid and c == true, a must be read. Depending on a, d might be read as well. 603eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // don't need to read b anymore because `a ? b : true` and `b ? a : false` has the same 604eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // invalidation flags. 605eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, a, abTernary, baTernary); 6067b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar justRead.clear(); 6077b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6087b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar readFirst = getReadFirst(shouldRead); 609eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // first must read `a`. 610eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(readFirst, a); 611eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar Collections.addAll(justRead, a); 6127b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6137b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead); 614eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(readFirst, abTernary, baTernary); 615eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar Collections.addAll(justRead, abTernary, baTernary); 616eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 617eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead); 618eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertEquals(0, filterOut(getReadFirst(shouldRead, justRead), justRead).size()); 619eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertTrue(mExprModel.markBitsRead()); 620eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 621eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar shouldRead = getShouldRead(); 622eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar // now we can read adf ternary and c ternary 623eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar justRead.clear(); 624eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, d, cTernary.getIfTrue(), cTernary); 625eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar readFirst = getReadFirst(shouldRead); 626eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(readFirst, d); 627eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar Collections.addAll(justRead, d); 628eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead); 629eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(readFirst, cTernary.getIfTrue()); 630eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar Collections.addAll(justRead, cTernary.getIfTrue()); 6317b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6327b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead); 6337b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(readFirst, cTernary); 6347b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar Collections.addAll(justRead, cTernary); 6357b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, filterOut(getReadFirst(shouldRead, justRead), justRead).size()); 6377b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6387b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertFalse(mExprModel.markBitsRead()); 6397b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 6407b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6417b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar @Test 642eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar public void testInterExprDeepDependency() { 643eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 644eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar mExprModel = lb.getModel(); 645eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar IdentifierExpr a = lb.addVariable("a", boolean.class.getCanonicalName(), null); 646eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar IdentifierExpr b = lb.addVariable("b", boolean.class.getCanonicalName(), null); 647eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar IdentifierExpr c = lb.addVariable("c", boolean.class.getCanonicalName(), null); 648eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar final TernaryExpr t1 = parse(lb, "c ? (a ? b : true) : false", TernaryExpr.class); 649eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar final TernaryExpr t2 = parse(lb, "c ? (b ? a : false) : true", TernaryExpr.class); 650eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar final TernaryExpr abTernary = (TernaryExpr) t1.getIfTrue(); 651eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar final TernaryExpr baTernary = (TernaryExpr) t2.getIfTrue(); 652eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar mExprModel.seal(); 653eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar List<Expr> shouldRead = getShouldRead(); 654eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, c); 655eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertTrue(mExprModel.markBitsRead()); 656eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar shouldRead = getShouldRead(); 657eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, a, b); 658eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertTrue(mExprModel.markBitsRead()); 659eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar shouldRead = getShouldRead(); 660eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertExactMatch(shouldRead, a, b, t1.getIfTrue(), t2.getIfTrue(), t1, t2); 661eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFlags(b, abTernary.getRequirementFlagIndex(true)); 662eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFlags(a, baTernary.getRequirementFlagIndex(true)); 663eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertFalse(mExprModel.markBitsRead()); 664eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar } 665eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar 666eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar @Test 6677b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar public void testInterExprDependencyNotReadyYet() { 668eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 6697b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel = lb.getModel(); 670c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr a = lb.addVariable("a", boolean.class.getCanonicalName(), null); 671c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr b = lb.addVariable("b", boolean.class.getCanonicalName(), null); 672c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr c = lb.addVariable("c", boolean.class.getCanonicalName(), null); 673c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr d = lb.addVariable("d", boolean.class.getCanonicalName(), null); 674c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr e = lb.addVariable("e", boolean.class.getCanonicalName(), null); 6757b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr cTernary = parse(lb, "c ? (a ? d : false) : false", TernaryExpr.class); 6767b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr baTernary = parse(lb, "b ? a : false", TernaryExpr.class); 6777b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar final TernaryExpr eaTernary = parse(lb, "e ? a : false", TernaryExpr.class); 6787b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar mExprModel.seal(); 6792611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 6807b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(shouldRead, b, c, e); 6817b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertTrue(mExprModel.markBitsRead()); 6827b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 6837b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(shouldRead, a, baTernary, eaTernary); 6847b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertTrue(mExprModel.markBitsRead()); 6857b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar shouldRead = getShouldRead(); 6867b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertExactMatch(shouldRead, d, cTernary.getIfTrue(), cTernary); 6877b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar assertFalse(mExprModel.markBitsRead()); 6887b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar } 6897b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar 6907b07818f07c28c6dec34ca2a9ab5f61e86afb493Yigit Boyar @Test 691dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar public void testNoFlagsForNonBindingStatic() { 692eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 693dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar mExprModel = lb.getModel(); 694c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar lb.addVariable("a", int.class.getCanonicalName(), null); 695dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar final MathExpr parsed = parse(lb, "a * (3 + 2)", MathExpr.class); 696dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar mExprModel.seal(); 697019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 698019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertEquals(1, parsed.getRight().getInvalidFlags().cardinality()); 699019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 700019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertEquals(2, parsed.getLeft().getInvalidFlags().cardinality()); 701019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 702019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertEquals(2, mExprModel.getInvalidateableFieldLimit()); 703dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar } 704dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar 705dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar @Test 706dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar public void testFlagsForBindingStatic() { 707eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 708dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar mExprModel = lb.getModel(); 709c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar lb.addVariable("a", int.class.getCanonicalName(), null); 710dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar final Expr staticParsed = parse(lb, "3 + 2", MathExpr.class); 711dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar final MathExpr parsed = parse(lb, "a * (3 + 2)", MathExpr.class); 712dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar mExprModel.seal(); 713dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar assertTrue(staticParsed.isBindingExpression()); 714019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 7158533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar assertEquals(1, staticParsed.getInvalidFlags().cardinality()); 716dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar assertEquals(parsed.getRight().getInvalidFlags(), staticParsed.getInvalidFlags()); 717019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 718019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertEquals(2, parsed.getLeft().getInvalidFlags().cardinality()); 719019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // +1 for invalidate all flag 7208533f27db6c31b0c295ae62d314dbf07ea640571Yigit Boyar assertEquals(2, mExprModel.getInvalidateableFieldLimit()); 721019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 722019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 723019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar @Test 724019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public void testFinalFieldOfAVariable() { 725eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 726019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel = lb.getModel(); 727c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar IdentifierExpr user = lb.addVariable("user", User.class.getCanonicalName(), 728c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 729019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar Expr fieldGet = parse(lb, "user.finalField", FieldAccessExpr.class); 730019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.seal(); 731019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertTrue(fieldGet.isDynamic()); 732019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // read user 733c96847768305d83c6bc4919432af9bd9bfe4c08eGeorge Mount assertExactMatch(getShouldRead(), user, fieldGet); 734019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.markBitsRead(); 735019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // no need to read user.finalField 7362611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 737019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 738019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 739019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar @Test 740019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public void testFinalFieldOfAField() { 741eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 742019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel = lb.getModel(); 743c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar lb.addVariable("user", User.class.getCanonicalName(), null); 744019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar Expr finalFieldGet = parse(lb, "user.subObj.finalField", FieldAccessExpr.class); 745019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.seal(); 746019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertTrue(finalFieldGet.isDynamic()); 747019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar Expr userSubObjGet = finalFieldGet.getChildren().get(0); 748019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // read user 7492611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 7502611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(3, shouldRead.size()); 751019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertExactMatch(shouldRead, userSubObjGet.getChildren().get(0), userSubObjGet, 752019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar finalFieldGet); 753019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.markBitsRead(); 754019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // no need to read user.subObj.finalField because it is final 7552611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 756019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 757019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 758019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar @Test 759019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public void testFinalFieldOfAMethod() { 760eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 761019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel = lb.getModel(); 762c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar lb.addVariable("user", User.class.getCanonicalName(), null); 763019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar Expr finalFieldGet = parse(lb, "user.anotherSubObj.finalField", FieldAccessExpr.class); 764019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.seal(); 765019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertTrue(finalFieldGet.isDynamic()); 766019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar Expr userSubObjGet = finalFieldGet.getChildren().get(0); 767019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // read user 7682611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> shouldRead = getShouldRead(); 7692611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(3, shouldRead.size()); 770019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertExactMatch(shouldRead, userSubObjGet.getChildren().get(0), userSubObjGet, 771019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar finalFieldGet); 772019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.markBitsRead(); 773019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar // no need to read user.subObj.finalField because it is final 7742611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 775dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar } 776dc69f49d687ec036947f26a9bf9025a305de0721Yigit Boyar 777019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar @Test 778019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public void testFinalOfAClass() { 779eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 780019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel = lb.getModel(); 781c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mExprModel.addImport("View", "android.view.View", null); 782019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar FieldAccessExpr fieldAccess = parse(lb, "View.VISIBLE", FieldAccessExpr.class); 783019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertFalse(fieldAccess.isDynamic()); 784019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.seal(); 7852611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 786019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 787019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 788019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar @Test 789ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar public void testStaticFieldOfInstance() { 790eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 791ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel = lb.getModel(); 792c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar lb.addVariable("myView", "android.view.View", null); 793ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar FieldAccessExpr fieldAccess = parse(lb, "myView.VISIBLE", FieldAccessExpr.class); 794ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertFalse(fieldAccess.isDynamic()); 795ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel.seal(); 7962611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 797ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar final Expr child = fieldAccess.getChild(); 798ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertTrue(child instanceof StaticIdentifierExpr); 799ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar StaticIdentifierExpr id = (StaticIdentifierExpr) child; 800ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertEquals(id.getResolvedType().getCanonicalName(), "android.view.View"); 801ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar // on demand import 802ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertEquals("android.view.View", mExprModel.getImports().get("View")); 803ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 804ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 805ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar @Test 806ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar public void testOnDemandImportConflict() { 807eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 808ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel = lb.getModel(); 809c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final IdentifierExpr myView = lb.addVariable("u", "android.view.View", 810c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 811c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mExprModel.addImport("View", User.class.getCanonicalName(), null); 812ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar final StaticIdentifierExpr id = mExprModel.staticIdentifierFor(myView.getResolvedType()); 813ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel.seal(); 814ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar // on demand import with conflict 815ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertEquals("android.view.View", mExprModel.getImports().get("View1")); 816ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertEquals("View1", id.getName()); 817ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertEquals("android.view.View", id.getUserDefinedType()); 818ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 819ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 820ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar @Test 821ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar public void testOnDemandImportAlreadyImported() { 822eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 823ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel = lb.getModel(); 824c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final StaticIdentifierExpr ux = mExprModel.addImport("UX", User.class.getCanonicalName(), 825c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 826c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final IdentifierExpr u = lb.addVariable("u", User.class.getCanonicalName(), 827c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar null); 828ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar final StaticIdentifierExpr id = mExprModel.staticIdentifierFor(u.getResolvedType()); 829ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel.seal(); 830ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar // on demand import with conflict 831ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertSame(ux, id); 832ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 833ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 834ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar @Test 835ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar public void testStaticMethodOfInstance() { 836eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 837ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel = lb.getModel(); 838c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar lb.addVariable("user", User.class.getCanonicalName(), null); 839ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar MethodCallExpr methodCall = parse(lb, "user.ourStaticMethod()", MethodCallExpr.class); 840ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertTrue(methodCall.isDynamic()); 841ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar mExprModel.seal(); 842ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar final Expr child = methodCall.getTarget(); 843ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertTrue(child instanceof StaticIdentifierExpr); 844ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar StaticIdentifierExpr id = (StaticIdentifierExpr) child; 845ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertEquals(id.getResolvedType().getCanonicalName(), User.class.getCanonicalName()); 846ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 847ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 848ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar @Test 849019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public void testFinalOfStaticField() { 850eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 851019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel = lb.getModel(); 852c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mExprModel.addImport("UX", User.class.getCanonicalName(), null); 853c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar FieldAccessExpr fieldAccess = parse(lb, "UX.innerStaticInstance.finalStaticField", 854c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar FieldAccessExpr.class); 855019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertFalse(fieldAccess.isDynamic()); 856019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.seal(); 857ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar // nothing to read since it is all final and static 8582611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 859019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 860019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 861019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar @Test 862019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public void testFinalOfFinalStaticField() { 863eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 864019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel = lb.getModel(); 865c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mExprModel.addImport("User", User.class.getCanonicalName(), null); 866c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar FieldAccessExpr fieldAccess = parse(lb, "User.innerFinalStaticInstance.finalStaticField", 867c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar FieldAccessExpr.class); 868019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar assertFalse(fieldAccess.isDynamic()); 869019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar mExprModel.seal(); 8702611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar assertEquals(0, getShouldRead().size()); 871019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 872019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 873c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar @Test 874c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar public void testLocationTracking() { 875eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar MockLayoutBinder lb = new MockLayoutBinder(); 876c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar mExprModel = lb.getModel(); 877c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final String input = "a > 3 ? b : c"; 878c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar TernaryExpr ternaryExpr = parse(lb, input, TernaryExpr.class); 879c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Location location = ternaryExpr.getLocations().get(0); 880c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertNotNull(location); 881c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, location.startLine); 882c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, location.startOffset); 883c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, location.endLine); 884c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(input.length() - 1, location.endOffset); 885c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 886c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final ComparisonExpr comparison = (ComparisonExpr) ternaryExpr.getPred(); 887c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Location predLoc = comparison.getLocations().get(0); 888c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertNotNull(predLoc); 889c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, predLoc.startLine); 890c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, predLoc.startOffset); 891c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, predLoc.endLine); 892c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(4, predLoc.endOffset); 893c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 894c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Location aLoc = comparison.getLeft().getLocations().get(0); 895c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertNotNull(aLoc); 896c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, aLoc.startLine); 897c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, aLoc.startOffset); 898c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, aLoc.endLine); 899c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, aLoc.endOffset); 900c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 901c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Location tLoc = comparison.getRight().getLocations().get(0); 902c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertNotNull(tLoc); 903c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, tLoc.startLine); 904c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(4, tLoc.startOffset); 905c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, tLoc.endLine); 906c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(4, tLoc.endOffset); 907c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 908c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Location bLoc = ternaryExpr.getIfTrue().getLocations().get(0); 909c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertNotNull(bLoc); 910c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, bLoc.startLine); 911c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(8, bLoc.startOffset); 912c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, bLoc.endLine); 913c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(8, bLoc.endOffset); 914c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 915c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar final Location cLoc = ternaryExpr.getIfFalse().getLocations().get(0); 916c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertNotNull(cLoc); 917c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, cLoc.startLine); 918c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(12, cLoc.startOffset); 919c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(0, cLoc.endLine); 920c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar assertEquals(12, cLoc.endOffset); 921c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar } 922c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 923019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// TODO uncomment when we have inner static access 924019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// @Test 925019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// public void testFinalOfInnerStaticClass() { 926eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar// MockLayoutBinder lb = new MockLayoutBinder(); 927019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// mExprModel = lb.getModel(); 928019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// mExprModel.addImport("User", User.class.getCanonicalName()); 929019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// FieldAccessExpr fieldAccess = parse(lb, "User.InnerStaticClass.finalStaticField", FieldAccessExpr.class); 930019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// assertFalse(fieldAccess.isDynamic()); 931019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// mExprModel.seal(); 9322611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar// assertEquals(0, getShouldRead().size()); 933019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar// } 934019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 935d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private void assertFlags(Expr a, int... flags) { 936d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet bitset = new BitSet(); 937d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (int flag : flags) { 938d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar bitset.set(flag); 939d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 940d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals("flag test for " + a.getUniqueKey(), bitset, a.getShouldReadFlags()); 941d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 942d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 943d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private void assertFlags(Expr a, Expr... exprs) { 944d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet bitSet = a.getShouldReadFlags(); 945d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : exprs) { 946d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet clone = (BitSet) bitSet.clone(); 947d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar clone.and(expr.getInvalidFlags()); 948d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals("should read flags of " + a.getUniqueKey() + " should include " + expr 949d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar .getUniqueKey(), expr.getInvalidFlags(), clone); 950d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 951d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 952d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar BitSet composite = new BitSet(); 953d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : exprs) { 954d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar composite.or(expr.getInvalidFlags()); 955d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 956d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertEquals("composite flags should match", composite, bitSet); 957d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 958d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 9592611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private void assertExactMatch(List<Expr> iterable, Expr... exprs) { 960d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar int i = 0; 961eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar String listLog = Arrays.toString(iterable.toArray()); 962eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar String itemsLog = Arrays.toString(exprs); 963eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar String log = "list: " + listLog + "\nitems: " + itemsLog; 964d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar log("list", iterable); 965d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : exprs) { 966ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar assertTrue((i++) + ":must contain " + expr.getUniqueKey() + "\n" + log, 9672611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar iterable.contains(expr)); 968d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 969d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar i = 0; 970d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr expr : iterable) { 971eebcbdd5d35e56a2c8ef37feeb65df46130d001dYigit Boyar assertTrue((i++) + ":must be expected " + expr.getUniqueKey() + "\n" + log, 9724ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta Arrays.asList(exprs).contains(expr)); 973d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 974d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 975d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 976d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar private <T extends Expr> T parse(LayoutBinder binder, String input, Class<T> klass) { 977d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount final Expr parsed = binder.parse(input, false, null); 978d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar assertTrue(klass.isAssignableFrom(parsed.getClass())); 979d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return (T) parsed; 980d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 981d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 9822611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private void log(String s, List<Expr> iterable) { 983d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar L.d(s); 984d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar for (Expr e : iterable) { 98574f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar L.d(": %s : %s allFlags: %s readSoFar: %s", e.getUniqueKey(), e.getShouldReadFlags(), 98674f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar e.getShouldReadFlagsWithConditionals(), e.getReadSoFar()); 987d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 988d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar L.d("end of %s", s); 989d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 990d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 9912611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private List<Expr> getReadFirst(List<Expr> shouldRead) { 9920fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar return getReadFirst(shouldRead, null); 9930fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar } 99474f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 9952611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private List<Expr> getReadFirst(List<Expr> shouldRead, final List<Expr> justRead) { 9962611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar List<Expr> result = new ArrayList<Expr>(); 9972611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar for (Expr expr : shouldRead) { 9982611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar if (expr.shouldReadNow(justRead)) { 9992611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar result.add(expr); 10000fa158e8aa91297cc246e3bb9e5d1388dc2355ccYigit Boyar } 10012611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar } 10022611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar return result; 1003d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1004d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 10052611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar private List<Expr> getShouldRead() { 1006af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar return ExprModel.filterShouldRead(mExprModel.getPendingExpressions()); 1007d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1008d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1009e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar public static class User implements Observable { 101074f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 1011d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar String name; 101274f72d77b1db2b78ee6422da2ec94de12edcb6dcYigit Boyar 1013d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar String lastName; 1014d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1015019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public final int finalField = 5; 1016c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1017019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public static InnerStaticClass innerStaticInstance = new InnerStaticClass(); 1018c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1019019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public static final InnerStaticClass innerFinalStaticInstance = new InnerStaticClass(); 1020c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1021019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public SubObj subObj = new SubObj(); 1022019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 1023d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getName() { 1024d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return name; 1025d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1026d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1027d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public String getLastName() { 1028d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return lastName; 1029d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1030d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar 1031d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar public boolean getCond(int i) { 1032d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar return true; 1033d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1034019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 1035019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public SubObj getAnotherSubObj() { 1036019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar return new SubObj(); 1037019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 1038019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 1039ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar public static boolean ourStaticMethod() { 1040ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar return true; 1041ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar } 1042ec2f3896c21a504b464bf591cdb45b62692b6760Yigit Boyar 1043d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount public String comment; 1044d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount 1045d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount @Bindable 1046876ba3272f17ed891ea455e7dd526d44e468757cYigit Boyar public boolean getUseComment() { 1047d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount return true; 1048d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount } 1049d615f15f0f0cc4c4de7570119d181e13d44e708aGeorge Mount 1050e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar @Override 1051e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) { 1052e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar 1053e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar } 1054e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar 1055e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar @Override 1056e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) { 1057e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar 1058e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar } 1059e61d1cc710803cdf0ab4f2aca3d18c46949758a9Yigit Boyar 1060019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public static class InnerStaticClass { 1061c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1062019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public static final int finalField = 3; 1063c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1064019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public static final int finalStaticField = 3; 1065019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 1066d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar } 1067019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 1068019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public static class SubObj { 1069c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar 1070019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar public final int finalField = 5; 1071019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar } 1072019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar 1073d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar} 1074