1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 package com.android.ide.eclipse.adt.internal.lint;
17 
18 import com.android.annotations.NonNull;
19 import com.android.annotations.Nullable;
20 import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest;
21 import com.android.tools.lint.checks.DuplicateIdDetector;
22 import com.android.tools.lint.checks.UnusedResourceDetector;
23 import com.android.tools.lint.client.api.Configuration;
24 import com.android.tools.lint.client.api.JavaParser;
25 import com.android.tools.lint.client.api.LintClient;
26 import com.android.tools.lint.client.api.XmlParser;
27 import com.android.tools.lint.detector.api.Context;
28 import com.android.tools.lint.detector.api.Issue;
29 import com.android.tools.lint.detector.api.Location;
30 import com.android.tools.lint.detector.api.Project;
31 import com.android.tools.lint.detector.api.Severity;
32 import com.android.tools.lint.detector.api.TextFormat;
33 
34 import org.eclipse.core.resources.IProject;
35 
36 import java.io.File;
37 
38 @SuppressWarnings("javadoc")
39 public class ProjectLintConfigurationTest extends AdtProjectTest {
testBasic()40     public void testBasic() {
41         Configuration parent = null;
42         LintClient client = new TestClient();
43 
44         File dir = getTargetDir();
45         if (!dir.exists()) {
46             boolean ok = dir.mkdirs();
47             assertTrue(dir.getPath(), ok);
48         }
49         Project project = client.getProject(dir, dir);
50 
51         ProjectLintConfiguration config =
52                 new ProjectLintConfiguration(client, project, parent, false /*fatalOnly*/);
53 
54         Issue usuallyEnabledIssue = DuplicateIdDetector.WITHIN_LAYOUT;
55         Issue usuallyDisabledIssue = UnusedResourceDetector.ISSUE_IDS;
56 
57         assertTrue(config.isEnabled(usuallyEnabledIssue));
58         assertFalse(config.isEnabled(usuallyDisabledIssue));
59 
60         config.setSeverity(usuallyEnabledIssue, Severity.IGNORE);
61         config.setSeverity(usuallyDisabledIssue, Severity.ERROR);
62         assertFalse(config.isEnabled(usuallyEnabledIssue));
63         assertTrue(config.isEnabled(usuallyDisabledIssue));
64 
65         // Make a NEW config object to ensure the state is persisted properly, not just
66         // kept on the config object!
67         config = new ProjectLintConfiguration(client, project, parent, false /*fatalOnly*/);
68         assertFalse(config.isEnabled(usuallyEnabledIssue));
69         assertTrue(config.isEnabled(usuallyDisabledIssue));
70     }
71 
testInheritance()72     public void testInheritance() {
73         Configuration parent = null;
74         LintClient client = new TestClient();
75 
76         File dir = getTargetDir();
77         assertTrue(dir.mkdirs());
78         Project project = client.getProject(dir, dir);
79 
80         File otherDir = new File(dir, "otherConfig");
81         assertTrue(otherDir.mkdir());
82         Project otherProject = client.getProject(otherDir, otherDir);
83 
84         ProjectLintConfiguration otherConfig =
85                 new ProjectLintConfiguration(client, otherProject, parent, false);
86 
87         ProjectLintConfiguration config =
88                 new ProjectLintConfiguration(client, project, otherConfig, false);
89 
90         Issue usuallyEnabledIssue = DuplicateIdDetector.WITHIN_LAYOUT;
91         Issue usuallyDisabledIssue = UnusedResourceDetector.ISSUE_IDS;
92 
93         assertTrue(config.isEnabled(usuallyEnabledIssue));
94         assertFalse(config.isEnabled(usuallyDisabledIssue));
95 
96         otherConfig.setSeverity(usuallyEnabledIssue, Severity.IGNORE);
97         otherConfig.setSeverity(usuallyDisabledIssue, Severity.ERROR);
98 
99         // Ensure inheritance works
100         assertFalse(config.isEnabled(usuallyEnabledIssue));
101         assertTrue(config.isEnabled(usuallyDisabledIssue));
102 
103         // Revert
104         otherConfig.setSeverity(usuallyEnabledIssue, Severity.ERROR);
105         otherConfig.setSeverity(usuallyDisabledIssue, Severity.IGNORE);
106         assertTrue(config.isEnabled(usuallyEnabledIssue));
107         assertFalse(config.isEnabled(usuallyDisabledIssue));
108 
109         // Now override in child
110         config.setSeverity(usuallyEnabledIssue, Severity.ERROR);
111         config.setSeverity(usuallyDisabledIssue, Severity.IGNORE);
112         assertTrue(config.isEnabled(usuallyEnabledIssue));
113         assertFalse(config.isEnabled(usuallyDisabledIssue));
114 
115         // Now change in parent: no change in child
116         otherConfig.setSeverity(usuallyEnabledIssue, Severity.IGNORE);
117         otherConfig.setSeverity(usuallyDisabledIssue, Severity.ERROR);
118         assertTrue(config.isEnabled(usuallyEnabledIssue));
119         assertFalse(config.isEnabled(usuallyDisabledIssue));
120         assertFalse(otherConfig.isEnabled(usuallyEnabledIssue));
121         assertTrue(otherConfig.isEnabled(usuallyDisabledIssue));
122 
123         // Clear override in child
124         config.setSeverity(usuallyEnabledIssue, null);
125         config.setSeverity(usuallyDisabledIssue, null);
126         assertFalse(config.isEnabled(usuallyEnabledIssue));
127         assertTrue(config.isEnabled(usuallyDisabledIssue));
128     }
129 
testBulkEditing()130     public void testBulkEditing() {
131         Configuration parent = null;
132         LintClient client = new TestClient();
133 
134         File dir = getTargetDir();
135         assertTrue(dir.mkdirs());
136         Project project = client.getProject(dir, dir);
137 
138         ProjectLintConfiguration config =
139                 new ProjectLintConfiguration(client, project, parent, false /*fatalOnly*/);
140 
141         Issue usuallyEnabledIssue = DuplicateIdDetector.WITHIN_LAYOUT;
142         Issue usuallyDisabledIssue = UnusedResourceDetector.ISSUE_IDS;
143 
144         assertTrue(config.isEnabled(usuallyEnabledIssue));
145         assertFalse(config.isEnabled(usuallyDisabledIssue));
146 
147         config.setSeverity(usuallyEnabledIssue, Severity.IGNORE);
148         assertFalse(config.isEnabled(usuallyEnabledIssue));
149         assertFalse(config.isEnabled(usuallyDisabledIssue));
150 
151         File configFile = new File(dir, "lint.xml");
152         assertTrue(configFile.getPath(), configFile.exists());
153         long lastModified = configFile.lastModified();
154 
155         // We need to make sure that the timestamp of the file is a couple of seconds
156         // after the last update or we can't tell whether the file was updated or not
157 
158         try {
159             Thread.sleep(1000);
160         } catch (InterruptedException e) {
161             System.err.println("Sleep interrupted, test may not work.");
162         }
163         config.startBulkEditing();
164         assertFalse(lastModified < configFile.lastModified());
165         assertEquals(lastModified, configFile.lastModified());
166         config.setSeverity(usuallyDisabledIssue, Severity.ERROR);
167         config.finishBulkEditing();
168         assertTrue(lastModified < configFile.lastModified());
169 
170         assertTrue(config.isEnabled(usuallyDisabledIssue));
171     }
172 
173     public void testPersistence() {
174         // Ensure that we use the same configuration object repeatedly for a
175         // single project, such that we don't recompute and parse XML for each and
176         // every lint run!
177         IProject project = getProject();
178         TestClient client = new TestClient();
179         ProjectLintConfiguration config1 = ProjectLintConfiguration.get(client, project, false);
180         ProjectLintConfiguration config2 = ProjectLintConfiguration.get(client, project, false);
181         assertSame(config1, config2);
182     }
183 
184     @Override
185     protected File getTargetDir() {
186         File targetDir = new File(getTempDir(), getClass().getSimpleName() + "_" + getName());
187         addCleanupDir(targetDir);
188         return targetDir;
189     }
190 
191     private static class TestClient extends LintClient {
192         @Override
193         public void report(@NonNull Context context, @NonNull Issue issue,
194                 @NonNull Severity severity, @Nullable Location location,
195                 @NonNull String message, @NonNull TextFormat format) {
196         }
197 
198         @Override
199         public void log(@NonNull Severity severity, @Nullable Throwable exception,
200                 @Nullable String format, @Nullable Object... args) {
201         }
202 
203         @Override
204         public XmlParser getXmlParser() {
205             return null;
206         }
207 
208         @Override
209         public @NonNull String readFile(@NonNull File file) {
210             return null;
211         }
212 
213         @Override
214         public JavaParser getJavaParser(@Nullable Project project) {
215             return null;
216         }
217     }
218 }
219