mobile/android/base/tests/testDistribution.java

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:9a6bec23b269
1 package org.mozilla.gecko.tests;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.InputStream;
6 import java.io.OutputStream;
7
8 import org.json.JSONArray;
9 import org.json.JSONException;
10 import org.json.JSONObject;
11 import org.mozilla.gecko.Actions;
12 import org.mozilla.gecko.Distribution;
13 import org.mozilla.gecko.db.BrowserContract;
14 import org.mozilla.gecko.util.ThreadUtils;
15
16 import android.app.Activity;
17 import android.content.SharedPreferences;
18
19 /**
20 * Tests distribution customization.
21 * mock-package.zip should contain the following directory structure:
22 *
23 * distribution/
24 * preferences.json
25 * bookmarks.json
26 * searchplugins/
27 * common/
28 * engine.xml
29 */
30 public class testDistribution extends ContentProviderTest {
31 private static final String MOCK_PACKAGE = "mock-package.zip";
32 private static final int PREF_REQUEST_ID = 0x7357;
33
34 private Activity mActivity;
35
36 /**
37 * This is a hack.
38 *
39 * Startup results in us writing prefs -- we fetch the Distribution, which
40 * caches its state. Our tests try to wipe those prefs, but apparently
41 * sometimes race with startup, which leads to us not getting one of our
42 * expected messages. The test fails.
43 *
44 * This hack waits for any existing background tasks -- such as the one that
45 * writes prefs -- to finish before we begin the test.
46 */
47 private void waitForBackgroundHappiness() {
48 final Object signal = new Object();
49 final Runnable done = new Runnable() {
50 @Override
51 public void run() {
52 synchronized (signal) {
53 signal.notify();
54 }
55 }
56 };
57 synchronized (signal) {
58 ThreadUtils.postToBackgroundThread(done);
59 try {
60 signal.wait();
61 } catch (InterruptedException e) {
62 mAsserter.ok(false, "InterruptedException waiting on background thread.", e.toString());
63 }
64 }
65 mAsserter.dumpLog("Background task completed. Proceeding.");
66 }
67
68 public void testDistribution() {
69 mActivity = getActivity();
70
71 String mockPackagePath = getMockPackagePath();
72
73 // Wait for any startup-related background distribution shenanigans to
74 // finish. This reduces the chance of us racing with startup pref writes.
75 waitForBackgroundHappiness();
76
77 // Pre-clear distribution pref, run basic preferences and en-US localized preferences Tests
78 clearDistributionPref();
79 setTestLocale("en-US");
80 initDistribution(mockPackagePath);
81 checkPreferences();
82 checkLocalizedPreferences("en-US");
83 checkSearchPlugin();
84
85 // Pre-clear distribution pref, and run es-MX localized preferences Test
86 clearDistributionPref();
87 setTestLocale("es-MX");
88 initDistribution(mockPackagePath);
89 checkLocalizedPreferences("es-MX");
90 }
91
92 // Initialize the distribution from the mock package.
93 private void initDistribution(String aPackagePath) {
94 // Call Distribution.init with the mock package.
95 Actions.EventExpecter distributionSetExpecter = mActions.expectGeckoEvent("Distribution:Set:OK");
96 Distribution.init(mActivity, aPackagePath, "prefs-" + System.currentTimeMillis());
97 distributionSetExpecter.blockForEvent();
98 distributionSetExpecter.unregisterListener();
99 }
100
101 // Test distribution and preferences values stored in preferences.json
102 private void checkPreferences() {
103 String prefID = "distribution.id";
104 String prefAbout = "distribution.about";
105 String prefVersion = "distribution.version";
106 String prefTestBoolean = "distribution.test.boolean";
107 String prefTestString = "distribution.test.string";
108 String prefTestInt = "distribution.test.int";
109
110 try {
111 final String[] prefNames = { prefID,
112 prefAbout,
113 prefVersion,
114 prefTestBoolean,
115 prefTestString,
116 prefTestInt };
117
118 Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
119 mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
120
121 JSONObject data = null;
122 int requestId = -1;
123
124 // Wait until we get the correct "Preferences:Data" event
125 while (requestId != PREF_REQUEST_ID) {
126 data = new JSONObject(eventExpecter.blockForEventData());
127 requestId = data.getInt("requestId");
128 }
129 eventExpecter.unregisterListener();
130
131 JSONArray preferences = data.getJSONArray("preferences");
132 for (int i = 0; i < preferences.length(); i++) {
133 JSONObject pref = (JSONObject) preferences.get(i);
134 String name = pref.getString("name");
135
136 if (name.equals(prefID)) {
137 mAsserter.is(pref.getString("value"), "test-partner", "check " + prefID);
138 } else if (name.equals(prefAbout)) {
139 mAsserter.is(pref.getString("value"), "Test Partner", "check " + prefAbout);
140 } else if (name.equals(prefVersion)) {
141 mAsserter.is(pref.getInt("value"), 1, "check " + prefVersion);
142 } else if (name.equals(prefTestBoolean)) {
143 mAsserter.is(pref.getBoolean("value"), true, "check " + prefTestBoolean);
144 } else if (name.equals(prefTestString)) {
145 mAsserter.is(pref.getString("value"), "test", "check " + prefTestString);
146 } else if (name.equals(prefTestInt)) {
147 mAsserter.is(pref.getInt("value"), 5, "check " + prefTestInt);
148 }
149 }
150
151 } catch (JSONException e) {
152 mAsserter.ok(false, "exception getting preferences", e.toString());
153 }
154 }
155
156 private void checkSearchPlugin() {
157 Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("SearchEngines:Data");
158 mActions.sendGeckoEvent("SearchEngines:GetVisible", null);
159
160 try {
161 JSONObject data = new JSONObject(eventExpecter.blockForEventData());
162 eventExpecter.unregisterListener();
163 JSONArray searchEngines = data.getJSONArray("searchEngines");
164 boolean foundEngine = false;
165 for (int i = 0; i < searchEngines.length(); i++) {
166 JSONObject engine = (JSONObject) searchEngines.get(i);
167 String name = engine.getString("name");
168 if (name.equals("Test search engine")) {
169 foundEngine = true;
170 break;
171 }
172 }
173 mAsserter.ok(foundEngine, "check search plugin", "found test search plugin");
174 } catch (JSONException e) {
175 mAsserter.ok(false, "exception getting search plugins", e.toString());
176 }
177 }
178
179 // Sets the distribution locale preference for the test
180 private void setTestLocale(String aLocale) {
181 String prefUseragentLocale = "general.useragent.locale";
182
183 JSONObject jsonPref = new JSONObject();
184 try {
185 // Request the pref change to the locale.
186 jsonPref.put("name", prefUseragentLocale);
187 jsonPref.put("type", "string");
188 jsonPref.put("value", aLocale);
189 mActions.sendGeckoEvent("Preferences:Set", jsonPref.toString());
190
191 // Wait for confirmation of the pref change.
192 final String[] prefNames = { prefUseragentLocale };
193
194 Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
195 mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
196
197 JSONObject data = null;
198 int requestId = -1;
199
200 // Wait until we get the correct "Preferences:Data" event
201 while (requestId != PREF_REQUEST_ID) {
202 data = new JSONObject(eventExpecter.blockForEventData());
203 requestId = data.getInt("requestId");
204 }
205 eventExpecter.unregisterListener();
206
207 } catch (Exception e) {
208 mAsserter.ok(false, "exception setting test locale", e.toString());
209 }
210 }
211
212 // Test localized distribution and preferences values stored in preferences.json
213 private void checkLocalizedPreferences(String aLocale) {
214 String prefAbout = "distribution.about";
215 String prefLocalizeable = "distribution.test.localizeable";
216 String prefLocalizeableOverride = "distribution.test.localizeable-override";
217
218 try {
219 final String[] prefNames = { prefAbout, prefLocalizeable, prefLocalizeableOverride };
220
221 Actions.RepeatedEventExpecter eventExpecter = mActions.expectGeckoEvent("Preferences:Data");
222 mActions.sendPreferencesGetEvent(PREF_REQUEST_ID, prefNames);
223
224 JSONObject data = null;
225 int requestId = -1;
226
227 // Wait until we get the correct "Preferences:Data" event
228 while (requestId != PREF_REQUEST_ID) {
229 data = new JSONObject(eventExpecter.blockForEventData());
230 requestId = data.getInt("requestId");
231 }
232 eventExpecter.unregisterListener();
233
234 JSONArray preferences = data.getJSONArray("preferences");
235 for (int i = 0; i < preferences.length(); i++) {
236 JSONObject pref = (JSONObject) preferences.get(i);
237 String name = pref.getString("name");
238
239 if (name.equals(prefAbout)) {
240 if (aLocale.equals("en-US")) {
241 mAsserter.is(pref.getString("value"), "Test Partner", "check " + prefAbout);
242 } else if (aLocale.equals("es-MX")) {
243 mAsserter.is(pref.getString("value"), "Afiliado de Prueba", "check " + prefAbout);
244 }
245 } else if (name.equals(prefLocalizeable)) {
246 if (aLocale.equals("en-US")) {
247 mAsserter.is(pref.getString("value"), "http://test.org/en-US/en-US/", "check " + prefLocalizeable);
248 } else if (aLocale.equals("es-MX")) {
249 mAsserter.is(pref.getString("value"), "http://test.org/es-MX/es-MX/", "check " + prefLocalizeable);
250 }
251 } else if (name.equals(prefLocalizeableOverride)) {
252 if (aLocale.equals("en-US")) {
253 mAsserter.is(pref.getString("value"), "http://cheese.com", "check " + prefLocalizeableOverride);
254 } else if (aLocale.equals("es-MX")) {
255 mAsserter.is(pref.getString("value"), "http://test.org/es-MX/", "check " + prefLocalizeableOverride);
256 }
257 }
258 }
259
260 } catch (JSONException e) {
261 mAsserter.ok(false, "exception getting preferences", e.toString());
262 }
263 }
264
265 // Copies the mock package to the data directory and returns the file path to it.
266 private String getMockPackagePath() {
267 String mockPackagePath = "";
268
269 try {
270 InputStream inStream = getAsset(MOCK_PACKAGE);
271 File dataDir = new File(mActivity.getApplicationInfo().dataDir);
272 File outFile = new File(dataDir, MOCK_PACKAGE);
273
274 OutputStream outStream = new FileOutputStream(outFile);
275 int b;
276 while ((b = inStream.read()) != -1) {
277 outStream.write(b);
278 }
279 inStream.close();
280 outStream.close();
281
282 mockPackagePath = outFile.getPath();
283
284 } catch (Exception e) {
285 mAsserter.ok(false, "exception copying mock distribution package to data directory", e.toString());
286 }
287
288 return mockPackagePath;
289 }
290
291 // Clears the distribution pref to return distribution state to STATE_UNKNOWN
292 private void clearDistributionPref() {
293 mAsserter.dumpLog("Clearing distribution pref.");
294 SharedPreferences settings = mActivity.getSharedPreferences("GeckoApp", Activity.MODE_PRIVATE);
295 String keyName = mActivity.getPackageName() + ".distribution_state";
296 settings.edit().remove(keyName).commit();
297 }
298
299 @Override
300 public void setUp() throws Exception {
301 // TODO: Set up the content provider after setting the distribution.
302 super.setUp(sBrowserProviderCallable, BrowserContract.AUTHORITY, "browser.db");
303 }
304
305 private void delete(File file) throws Exception {
306 if (file.isDirectory()) {
307 File[] files = file.listFiles();
308 for (File f : files) {
309 delete(f);
310 }
311 }
312 mAsserter.ok(file.delete(), "clean up distribution files", "deleted " + file.getPath());
313 }
314
315 @Override
316 public void tearDown() throws Exception {
317 File dataDir = new File(mActivity.getApplicationInfo().dataDir);
318
319 // Delete mock package from data directory.
320 File mockPackage = new File(dataDir, MOCK_PACKAGE);
321 mAsserter.ok(mockPackage.delete(), "clean up mock package", "deleted " + mockPackage.getPath());
322
323 // Recursively delete distribution files that Distribution.init copied to data directory.
324 File distDir = new File(dataDir, "distribution");
325 delete(distDir);
326
327 clearDistributionPref();
328
329 super.tearDown();
330 }
331 }

mercurial