1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.databinding.tool.expr; 18 19 import android.databinding.tool.LayoutBinder; 20 import android.databinding.tool.MockLayoutBinder; 21 import android.databinding.tool.reflection.ModelAnalyzer; 22 import android.databinding.tool.reflection.ModelClass; 23 import android.databinding.tool.reflection.java.JavaAnalyzer; 24 import android.databinding.tool.writer.KCode; 25 26 import org.junit.Before; 27 import org.junit.Test; 28 29 import java.util.BitSet; 30 import java.util.List; 31 32 import static org.junit.Assert.assertEquals; 33 import static org.junit.Assert.assertTrue; 34 35 public class ExprTest{ 36 private static class DummyExpr extends Expr { 37 String mKey; 38 public DummyExpr(String key, DummyExpr... children) { 39 super(children); 40 mKey = key; 41 } 42 43 @Override 44 protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) { 45 return modelAnalyzer.findClass(Integer.class); 46 } 47 48 @Override 49 protected List<Dependency> constructDependencies() { 50 return constructDynamicChildrenDependencies(); 51 } 52 53 @Override 54 protected String computeUniqueKey() { 55 return mKey + super.computeUniqueKey(); 56 } 57 58 @Override 59 protected KCode generateCode() { 60 return new KCode(); 61 } 62 63 @Override 64 public Expr cloneToModel(ExprModel model) { 65 return this; 66 } 67 68 @Override 69 protected String getInvertibleError() { 70 return null; 71 } 72 73 @Override 74 public boolean isDynamic() { 75 return true; 76 } 77 } 78 79 @Before 80 public void setUp() throws Exception { 81 JavaAnalyzer.initForTests(); 82 } 83 84 @Test(expected=Throwable.class) 85 public void testBadExpr() { 86 Expr expr = new Expr() { 87 @Override 88 protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) { 89 return modelAnalyzer.findClass(Integer.class); 90 } 91 92 @Override 93 protected List<Dependency> constructDependencies() { 94 return constructDynamicChildrenDependencies(); 95 } 96 97 @Override 98 protected KCode generateCode() { 99 return new KCode(); 100 } 101 102 @Override 103 public Expr cloneToModel(ExprModel model) { 104 return this; 105 } 106 107 @Override 108 protected String getInvertibleError() { 109 return null; 110 } 111 }; 112 expr.getUniqueKey(); 113 } 114 115 @Test 116 public void testBasicInvalidationFlag() { 117 LayoutBinder lb = new MockLayoutBinder(); 118 ExprModel model = lb.getModel(); 119 model.seal(); 120 DummyExpr d = new DummyExpr("a"); 121 d.setModel(model); 122 d.setId(3); 123 d.enableDirectInvalidation(); 124 assertTrue(d.getInvalidFlags().get(3)); 125 BitSet clone = (BitSet) model.getInvalidateAnyBitSet().clone(); 126 clone.and(d.getInvalidFlags()); 127 assertEquals(1, clone.cardinality()); 128 } 129 130 @Test 131 public void testCannotBeInvalidated() { 132 LayoutBinder lb = new MockLayoutBinder(); 133 ExprModel model = lb.getModel(); 134 model.seal(); 135 DummyExpr d = new DummyExpr("a"); 136 d.setModel(model); 137 d.setId(3); 138 // +1 for invalidate all flag 139 assertEquals(1, d.getInvalidFlags().cardinality()); 140 assertEquals(model.getInvalidateAnyBitSet(), d.getInvalidFlags()); 141 } 142 143 @Test 144 public void testInvalidationInheritance() { 145 ExprModel model = new ExprModel(); 146 DummyExpr a = model.register(new DummyExpr("a")); 147 DummyExpr b = model.register(new DummyExpr("b")); 148 DummyExpr c = model.register(new DummyExpr("c", a, b)); 149 a.enableDirectInvalidation(); 150 b.enableDirectInvalidation(); 151 c.setBindingExpression(true); 152 model.seal(); 153 assertFlags(c, a, b); 154 } 155 156 @Test 157 public void testInvalidationInheritance2() { 158 ExprModel model = new ExprModel(); 159 DummyExpr a = model.register(new DummyExpr("a")); 160 DummyExpr b = model.register(new DummyExpr("b", a)); 161 DummyExpr c = model.register(new DummyExpr("c", b)); 162 a.enableDirectInvalidation(); 163 b.enableDirectInvalidation(); 164 c.setBindingExpression(true); 165 model.seal(); 166 assertFlags(c, a, b); 167 } 168 169 @Test 170 public void testShouldReadFlags() { 171 ExprModel model = new ExprModel(); 172 DummyExpr a = model.register(new DummyExpr("a")); 173 a.enableDirectInvalidation(); 174 a.setBindingExpression(true); 175 model.seal(); 176 assertFlags(a, a); 177 } 178 179 @Test 180 public void testShouldReadDependencyFlags() { 181 ExprModel model = new ExprModel(); 182 DummyExpr a = model.register(new DummyExpr("a")); 183 DummyExpr b = model.register(new DummyExpr("b", a)); 184 DummyExpr c = model.register(new DummyExpr("c", b)); 185 a.enableDirectInvalidation(); 186 b.enableDirectInvalidation(); 187 b.setBindingExpression(true); 188 c.setBindingExpression(true); 189 model.seal(); 190 assertFlags(b, a, b); 191 assertFlags(c, a, b); 192 } 193 194 private void assertFlags(Expr a, Expr... exprs) { 195 BitSet bitSet = a.getShouldReadFlags(); 196 for (Expr expr : exprs) { 197 BitSet clone = (BitSet) bitSet.clone(); 198 clone.and(expr.getInvalidFlags()); 199 assertEquals("should read flags of " + a.getUniqueKey() + " should include " + expr 200 .getUniqueKey(), expr.getInvalidFlags(), clone); 201 } 202 203 BitSet composite = new BitSet(); 204 for (Expr expr : exprs) { 205 composite.or(expr.getInvalidFlags()); 206 } 207 assertEquals("composite flags should match", composite, bitSet); 208 } 209 } 210