View Javadoc
1   /*
2    * Copyright © 2017, Salesforce.com, Inc
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *     * Redistributions of source code must retain the above copyright
8    *       notice, this list of conditions and the following disclaimer.
9    *     * Redistributions in binary form must reproduce the above copyright
10   *       notice, this list of conditions and the following disclaimer in the
11   *       documentation and/or other materials provided with the distribution.
12   *     * Neither the name of the <organization> nor the
13   *       names of its contributors may be used to endorse or promote products
14   *       derived from this software without specific prior written permission.
15   *
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  package com.salesforce.apt.graph.processing;
28  
29  import static org.assertj.core.api.Assertions.assertThat;
30  
31  import java.io.File;
32  import java.util.Arrays;
33  import java.util.List;
34  import java.util.Set;
35  
36  import org.junit.Rule;
37  import org.junit.Test;
38  import org.junit.rules.TemporaryFolder;
39  
40  import com.salesforce.apt.graph.model.DefinitionModel;
41  import com.salesforce.apt.graph.model.ExpectedModel;
42  import com.salesforce.apt.graph.model.InstanceDependencyModel;
43  import com.salesforce.apt.graph.model.InstanceModel;
44  import com.salesforce.apt.graph.model.errors.ErrorType;
45  import com.salesforce.apt.graph.model.storage.DefinitionModelStore;
46  import com.salesforce.apt.graph.model.storage.ResourceLoader;
47  import com.salesforce.apt.graph.model.storage.classpath.ClasspathUrlResourceLoader;
48  import com.salesforce.apt.graph.model.storage.classpath.GsonDefinitionModelStore;
49  import com.salesforce.apt.graph.model.storage.classpath.TestFileStore;
50  import com.salesforce.apt.graph.test.cycle.definitions.TestErrorListener;
51  import com.salesforce.apt.graph.types.impl.ReflectionAssignabilityUtils;
52  
53  public class TestDefinitionInspector {
54    
55    private static final String TEST_DEF1 = "test.Def1";
56    private static final String TEST_DEF2 = "test.Def2";
57    private static final String TEST_DEF3 = "test.Def3";
58    private static final String TEST_DEF4 = "test.Def4";
59    
60    private static final String OBJECT1 = "object1";
61    private static final String OBJECT1_SOURCE = "test.Def1.object1(...)";
62    
63    private static final String OBJECT2 = "object2";
64    private static final String OBJECT2_SOURCE = "test.Def2.object2(...)";
65    
66    //private static final String OBJECT3 = "object3";
67    //private static final String OBJECT3_SOURCE = "test.Def3.object3(...)";
68    
69    private static final String TYPE_CHARSEQUENCE = "java.lang.CharSequence";
70    private static final String TYPE_STRING = "java.lang.String";
71    //private static final String TYPE_STRINGBUILDER = "java.lang.StringBuilder";
72    
73    @Rule
74    public TemporaryFolder testFolder = new TemporaryFolder();
75  
76    private static DefinitionModelStore getDefinitionModelStore(File root) {
77      TestFileStore fileStore = new TestFileStore(root);
78      ResourceLoader loader = new ClasspathUrlResourceLoader(root);
79      return new GsonDefinitionModelStore(loader, fileStore);
80    }
81    
82    @Test
83    public void inspectGraphForHead() {
84      DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
85      model1.addDependencyNames(Arrays.asList(TEST_DEF2));
86      DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
87      model2.addDependencyNames(Arrays.asList());
88      TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
89      List<DefinitionModel> definitions = Arrays.asList(model1, model2);
90      new DefinitionJoiner().joinDefinitions(definitions, getDefinitionModelStore(testFolder.getRoot()), el);
91      assertThat(el.getErrors()).isEmpty();
92      Set<DefinitionModel> heads = new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
93      assertThat(heads).containsOnly(model1);
94      assertThat(el.getErrors()).isEmpty();
95    }
96  
97    @Test
98    public void inspectGraphForHeads() {
99      DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
100     model1.addDependencyNames(Arrays.asList(TEST_DEF2));
101     DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
102     model2.addDependencyNames(Arrays.asList());
103     DefinitionModel model3 = new DefinitionModel(TEST_DEF3);
104     model3.addDependencyNames(Arrays.asList(TEST_DEF2));
105     TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
106     List<DefinitionModel> definitions = Arrays.asList(model1, model2, model3);
107     new DefinitionJoiner().joinDefinitions(definitions, getDefinitionModelStore(testFolder.getRoot()), el);
108     assertThat(el.getErrors()).isEmpty();
109     Set<DefinitionModel> heads = new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
110     assertThat(heads).containsOnly(model1, model3);
111     assertThat(el.getErrors()).isEmpty();
112   }
113 
114   @Test
115   public void inspectGraphHasCycle() {
116     DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
117     model1.addDependencyNames(Arrays.asList(TEST_DEF2));
118     DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
119     model2.addDependencyNames(Arrays.asList(TEST_DEF3));
120     DefinitionModel model3 = new DefinitionModel(TEST_DEF3);
121     model3.addDependencyNames(Arrays.asList(TEST_DEF1));
122     TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
123     List<DefinitionModel> definitions = Arrays.asList(model1, model2, model3);
124     new DefinitionJoiner().joinDefinitions(definitions, getDefinitionModelStore(testFolder.getRoot()), el);
125     assertThat(el.getErrors()).isEmpty();
126     Set<DefinitionModel> heads = new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
127     assertThat(heads).isEmpty();
128     assertThat(el.getErrors()).hasSize(1);
129     assertThat(el.getErrors().get(0).getMessage()).isEqualByComparingTo(ErrorType.CYCLE_IN_DEFINITION_SOURCES);
130     assertThat(el.getErrors().get(0).getInvolved()).containsOnly(model1,model2,model3);
131   }
132   
133   @Test
134   public void inspectGraphHasCycles() {
135     DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
136     model1.addDependencyNames(Arrays.asList(TEST_DEF2));
137     //model1.addDefinition(new InstanceModel("object1", "test.Ob1", "java.lang.String", Arrays.asList("object2")));
138     DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
139     model2.addDependencyNames(Arrays.asList(TEST_DEF3,TEST_DEF4));
140     //model2.addDefinition(new InstanceModel("object2", "test.Ob2", "java.lang.String", Arrays.asList()));
141     DefinitionModel model3 = new DefinitionModel(TEST_DEF3);
142     model3.addDependencyNames(Arrays.asList(TEST_DEF2));
143     //model3.addDefinition(new InstanceModel("object3", "test.Ob2", "java.lang.String", Arrays.asList()));
144     DefinitionModel model4 = new DefinitionModel("test.Def4");
145     model4.addDependencyNames(Arrays.asList(TEST_DEF2));
146     TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
147     List<DefinitionModel> definitions = Arrays.asList(model1, model2, model3, model4);
148     new DefinitionJoiner().joinDefinitions(definitions, getDefinitionModelStore(testFolder.getRoot()), el);
149     assertThat(el.getErrors()).isEmpty();
150     Set<DefinitionModel> heads = new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
151     assertThat(heads).contains(model1);
152     assertThat(el.getErrors()).hasSize(2);
153     assertThat(el.getErrors()).allMatch(em -> em.getMessage().equals(ErrorType.CYCLE_IN_DEFINITION_SOURCES));
154     assertThat(el.getErrors().get(0).getInvolved()).containsOnly(model2,model3);
155     assertThat(el.getErrors().get(1).getInvolved()).containsOnly(model2,model4);
156   }
157   
158   @Test
159   public void inspectGraphProperlyListsExpectedEntities() {
160     DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
161     model1.addDefinition(new ExpectedModel(OBJECT2));
162     model1.addDefinition(new InstanceModel(OBJECT1, TEST_DEF1, OBJECT1_SOURCE, TYPE_STRING,
163         Arrays.asList(new InstanceDependencyModel(OBJECT2, TYPE_STRING)), Arrays.asList()));
164     DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
165     model2.addDefinition(new InstanceModel(OBJECT2, TEST_DEF1, OBJECT2_SOURCE, TYPE_STRING, Arrays.asList(), Arrays.asList()));
166     TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
167     List<DefinitionModel> definitions = Arrays.asList(model1, model2);
168     new DefinitionJoiner().joinDefinitions(definitions, getDefinitionModelStore(testFolder.getRoot()), el);
169     assertThat(el.getErrors()).isEmpty();
170     new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
171     assertThat(el.getErrors()).isEmpty();
172   }
173 
174   @Test
175   public void inspectGraphComplainsAboutMismatchedTypesExpectedEntity() {
176     DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
177     model1.addDependencyNames(TEST_DEF2);
178     //model1.addDefinition(new ExpectedModel(OBJECT2));  //wants a string not charsequence
179     InstanceModel instance1 = new InstanceModel(OBJECT1, TEST_DEF1, OBJECT1_SOURCE, TYPE_STRING,
180         Arrays.asList(new InstanceDependencyModel(OBJECT2, TYPE_STRING)), Arrays.asList());
181     model1.addDefinition(instance1);
182     DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
183     //provides a char sequence
184     InstanceModel instance2 = new InstanceModel(OBJECT2, TEST_DEF1, OBJECT2_SOURCE, TYPE_CHARSEQUENCE, Arrays.asList(),
185         Arrays.asList());
186     model2.addDefinition(instance2);
187 
188     DefinitionModelStore store = getDefinitionModelStore(testFolder.getRoot());
189     TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
190     List<DefinitionModel> definitions = Arrays.asList(model1, model2);
191     new DefinitionJoiner().joinDefinitions(definitions, store, el);
192     Set<DefinitionModel> definitionHeads = new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
193     assertThat(el.getErrors()).isEmpty();
194     
195     new DefinitionContentInspector().inspectDefinitionGraph(definitionHeads, el, new ReflectionAssignabilityUtils(), store);
196     assertThat(el.getErrors()).hasSize(1);
197     assertThat(el.getErrors().get(0).getMessage()).isEqualByComparingTo(ErrorType.UNMATCHED_TYPES);
198     assertThat(el.getErrors().get(0).getCauses()).containsExactly(instance1, instance2);
199     assertThat(el.getErrors().get(0).getInvolved()).containsExactly(instance1, instance2);
200   }
201   
202   @Test
203   public void inspectGraphComplainsAboutUnusedExpectedEntity() {
204     DefinitionModel model1 = new DefinitionModel(TEST_DEF1);
205     model1.addDependencyNames(TEST_DEF2);
206     ExpectedModel expected1 = new ExpectedModel(OBJECT2);
207     model1.addDefinition(expected1); //is unused
208     InstanceModel instance1 = new InstanceModel(OBJECT1, TEST_DEF1, OBJECT1_SOURCE, TYPE_STRING,
209         Arrays.asList(new InstanceDependencyModel(OBJECT2, TYPE_STRING)), Arrays.asList());
210     model1.addDefinition(instance1);
211     DefinitionModel model2 = new DefinitionModel(TEST_DEF2);
212     //provides a char sequence
213     InstanceModel instance2 = new InstanceModel(OBJECT2, TEST_DEF2, OBJECT2_SOURCE, TYPE_STRING, Arrays.asList(),
214         Arrays.asList());
215     model2.addDefinition(instance2);
216     DefinitionModelStore store = getDefinitionModelStore(testFolder.getRoot());
217     
218     TestErrorListenercle/definitions/TestErrorListener.html#TestErrorListener">TestErrorListener el = new TestErrorListener();
219     List<DefinitionModel> definitions = Arrays.asList(model1, model2);
220     new DefinitionJoiner().joinDefinitions(definitions, store, el);
221     Set<DefinitionModel> definitionHeads = new DefinitionGraphInpector().inspectDefinitionGraph(definitions, el);
222     assertThat(el.getErrors()).isEmpty();
223     new DefinitionContentInspector().inspectDefinitionGraph(definitionHeads, el, new ReflectionAssignabilityUtils(), store);
224     assertThat(el.getErrors()).hasSize(1);
225     assertThat(el.getErrors().get(0).getMessage()).isEqualByComparingTo(ErrorType.UNUSED_EXPECTED);
226     assertThat(el.getErrors().get(0).getCauses()).containsExactly(expected1);
227     assertThat(el.getErrors().get(0).getInvolved()).containsExactly(model1);
228   }
229 }