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
19019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarimport android.databinding.tool.LayoutBinder;
20019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyarimport android.databinding.tool.MockLayoutBinder;
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer;
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelClass;
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.java.JavaAnalyzer;
24e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mountimport android.databinding.tool.writer.KCode;
25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount
26d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.Before;
27d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mountimport org.junit.Test;
28d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
29d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.BitSet;
30d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport java.util.List;
31d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
32d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport static org.junit.Assert.assertEquals;
33d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarimport static org.junit.Assert.assertTrue;
34d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
35d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyarpublic class ExprTest{
36d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private static class DummyExpr extends Expr {
37d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        String mKey;
38d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        public DummyExpr(String key, DummyExpr... children) {
39d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            super(children);
40d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            mKey = key;
41d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
42d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
43d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        @Override
4497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
4597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            return modelAnalyzer.findClass(Integer.class);
46d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
47d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
48d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        @Override
49d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        protected List<Dependency> constructDependencies() {
50d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return constructDynamicChildrenDependencies();
51d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
52d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
53d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        @Override
54d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        protected String computeUniqueKey() {
55d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return mKey + super.computeUniqueKey();
56d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
57d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
58d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        @Override
59d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        protected KCode generateCode(boolean full) {
60e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount            return new KCode();
61e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount        }
62e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount
63e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount        @Override
64d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        protected String getInvertibleError() {
65d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            return null;
66d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        }
67d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
68d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        @Override
69d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        public boolean isDynamic() {
70d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            return true;
71d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
72d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
73d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
74d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Before
75d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void setUp() throws Exception {
7697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        JavaAnalyzer.initForTests();
77d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
78d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
792611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyar    @Test(expected=Throwable.class)
80d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testBadExpr() {
81d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        Expr expr = new Expr() {
82d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            @Override
8397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
8497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                return modelAnalyzer.findClass(Integer.class);
85d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
86d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
87d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            @Override
88d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            protected List<Dependency> constructDependencies() {
89d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                return constructDynamicChildrenDependencies();
90d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            }
91e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount
92e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount            @Override
93d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            protected KCode generateCode(boolean full) {
94e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount                return new KCode();
95e52882df6130221462bf07f5f2b52de5c4b0f8deGeorge Mount            }
96d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
97d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            @Override
98d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            protected String getInvertibleError() {
99d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                return null;
100d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            }
101d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        };
102d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        expr.getUniqueKey();
103d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
104d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
105d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Test
106d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testBasicInvalidationFlag() {
107019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        LayoutBinder lb = new MockLayoutBinder();
108019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        ExprModel model = lb.getModel();
109019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        model.seal();
110d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr d = new DummyExpr("a");
111019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        d.setModel(model);
112d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        d.setId(3);
113d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        d.enableDirectInvalidation();
114d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertTrue(d.getInvalidFlags().get(3));
115019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        BitSet clone = (BitSet) model.getInvalidateAnyBitSet().clone();
116019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        clone.and(d.getInvalidFlags());
117019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        assertEquals(1, clone.cardinality());
118d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
119d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
120d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Test
121d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testCannotBeInvalidated() {
122019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        LayoutBinder lb = new MockLayoutBinder();
123019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        ExprModel model = lb.getModel();
124019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        model.seal();
125d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr d = new DummyExpr("a");
126019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        d.setModel(model);
127d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        d.setId(3);
128019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        // +1 for invalidate all flag
129019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        assertEquals(1, d.getInvalidFlags().cardinality());
130019c36b97c7c172ac03997f6bf170e65b2ed7fe4Yigit Boyar        assertEquals(model.getInvalidateAnyBitSet(), d.getInvalidFlags());
131d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
132d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
133d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Test
134d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testInvalidationInheritance() {
135d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        ExprModel model = new ExprModel();
136d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr a = model.register(new DummyExpr("a"));
137d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr b = model.register(new DummyExpr("b"));
138d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr c = model.register(new DummyExpr("c", a, b));
139d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        a.enableDirectInvalidation();
140d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        b.enableDirectInvalidation();
141d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c.setBindingExpression(true);
142d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.seal();
143d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertFlags(c, a, b);
144d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
145d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
146d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Test
147d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testInvalidationInheritance2() {
148d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        ExprModel model = new ExprModel();
149d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr a = model.register(new DummyExpr("a"));
150d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr b = model.register(new DummyExpr("b", a));
151d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr c = model.register(new DummyExpr("c", b));
152d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        a.enableDirectInvalidation();
153d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        b.enableDirectInvalidation();
154d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c.setBindingExpression(true);
155d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.seal();
156d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertFlags(c, a, b);
157d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
158d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
159d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Test
160d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testShouldReadFlags() {
161d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        ExprModel model = new ExprModel();
162d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr a = model.register(new DummyExpr("a"));
163d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        a.enableDirectInvalidation();
164d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        a.setBindingExpression(true);
165d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.seal();
166d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertFlags(a, a);
167d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
168d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
169d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    @Test
170d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    public void testShouldReadDependencyFlags() {
171d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        ExprModel model = new ExprModel();
172d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr a = model.register(new DummyExpr("a"));
173d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr b = model.register(new DummyExpr("b", a));
174d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        DummyExpr c = model.register(new DummyExpr("c", b));
175d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        a.enableDirectInvalidation();
176d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        b.enableDirectInvalidation();
177d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        b.setBindingExpression(true);
178d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        c.setBindingExpression(true);
179d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        model.seal();
180d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertFlags(b, a, b);
181d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertFlags(c, a, b);
182d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
183d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
184d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    private void assertFlags(Expr a, Expr... exprs) {
185d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        BitSet bitSet = a.getShouldReadFlags();
186d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        for (Expr expr : exprs) {
187d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            BitSet clone = (BitSet) bitSet.clone();
188d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            clone.and(expr.getInvalidFlags());
189d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            assertEquals("should read flags of " + a.getUniqueKey() + " should include " + expr
190d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar                    .getUniqueKey(), expr.getInvalidFlags(), clone);
191d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
192d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar
193d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        BitSet composite = new BitSet();
194d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        for (Expr expr : exprs) {
195d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar            composite.or(expr.getInvalidFlags());
196d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        }
197d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar        assertEquals("composite flags should match", composite, bitSet);
198d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar    }
199d7af42b29ddf22f0068f7496c5ac6f4f34b543b6Yigit Boyar}
200