test_filesystemsession.js
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2009 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25 */
26 
27 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
28 
29 const STATE_PHASE1 = "PHASE 1";
30 const STATE_PHASE2 = "PHASE 2";
31 const STATE_PHASE3 = "PHASE 3";
32 
33 
34 //
35 // \brief This test will test the session support for the filesystem API.
36 //
37 function runTest()
38 {
39  // If the file-system watcher is not supported on this system, just return.
40  var fsWatcher = Cc["@songbirdnest.com/filesystem/watcher;1"]
41  .createInstance(Ci.sbIFileSystemWatcher);
42  if (!fsWatcher.isSupported) {
43  return;
44  }
45 
46  // Create a directory to use for testing:
47  var watchDir = Cc["@mozilla.org/file/directory_service;1"]
48  .getService(Ci.nsIProperties)
49  .get("ProfD", Ci.nsIFile);
50 
51  watchDir.normalize();
52  watchDir.append("watch_dir");
53  if (!watchDir.exists() || !watchDir.isDirectory()) {
54  watchDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
55  }
56 
57  var listener = new sbFSListener(watchDir, fsWatcher);
58  listener.startTest();
59  testPending();
60 }
61 
62 
63 //
64 // \brief Create a FS listener
65 //
66 function sbFSListener(aWatchDir, aFSWatcher)
67 {
68  this._watchDir = aWatchDir;
69  this._fsWatcher = aFSWatcher;
70 }
71 
72 sbFSListener.prototype =
73 {
74  _state: "",
75  _savedSessionID: null,
76  _addedFile: null,
77  _changeFile: null,
78  _removeFile: null,
79  _shutdownTimer: null,
80  _restartTimer: null,
81  _addedFile: null,
82  _changedFile: null,
83  _removedFile: null,
84  _receivedAddedEvent: false,
85  _receivedChangedEvent: false,
86  _receivedRemovedEvent: false,
87 
88  _log: function(aMessage)
89  {
90  dump("----------------------------------------------------------\n");
91  dump(" " + aMessage + "\n");
92  dump("----------------------------------------------------------\n");
93  },
94 
95  _cleanup: function()
96  {
97  this._addedFile.remove(false);
98  this._addedFile = null;
99 
100  this._removeFile = null;
101 
102  this._changeFile.remove(false);
103  this._changeFile = null;
104 
105  this._watchDir.remove(true);
106  this._watchDir = null;
107 
108  this._shutdownTimer = null;
109  this._restartTimer = null;
110 
111  this._fsWatcher = null;
112  testFinished();
113  },
114 
115  //
116  // \brief Start running the session testing.
117  //
118  startTest: function()
119  {
120  this._log("Starting 'filesystemsession' test");
121 
122  this._shutdownTimer = Cc["@mozilla.org/timer;1"]
123  .createInstance(Ci.nsITimer);
124  this._restartTimer = Cc["@mozilla.org/timer;1"]
125  .createInstance(Ci.nsITimer);
126 
127  // Create some test files before watching starts for the first time.
128  this._addedFile = this._watchDir.clone();
129  this._addedFile.append("added.file");
130  if (this._addedFile.exists()) {
131  this._addedFile.remove(false);
132  }
133 
134  this._changeFile = this._watchDir.clone();
135  this._changeFile.append("changed.file");
136  if (!this._changeFile.exists()) {
137  this._changeFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0777);
138  }
139 
140  this._removeFile = this._watchDir.clone();
141  this._removeFile.append("removed.file");
142  if (!this._removeFile.exists()) {
143  this._removeFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0777);
144  }
145 
146  // Set the state to phase 1.
147  this._state = STATE_PHASE1;
148  this._log(this._state + ": Starting");
149 
150  this._fsWatcher.init(this, this._watchDir.path, true);
151  this._fsWatcher.startWatching();
152  },
153 
154  // sbIFileSystemListener
155  onWatcherStarted: function()
156  {
157  switch (this._state) {
158  case STATE_PHASE1:
159  {
160  this._log(this._state + ": Watcher has started");
161  // In this phase, we just want to shut the watcher back down to get
162  // a saved session GUID and create some serialized data on disk.
163 
164  // In this phase, just save the session ID and shutdown the watcher
165  // with the flag to save the session.
166  this._log(this._state + ": Stopping watcher, saving session.");
167  this._savedSessionID = this._fsWatcher.sessionGuid;
168  this._shutdownTimer.initWithCallback(this,
169  1000,
170  Ci.nsITimerCallback.TYPE_ONE_SHOT);
171  break;
172  }
173 
174  case STATE_PHASE2:
175  {
176  this._log(this._state + ": Watcher has started");
177  // Ensure that the file system events where received. All events that
178  // have been discovered between application sessions get reported
179  // before |onWatcherStarted()|.
180  assertTrue(this._receivedAddedEvent);
181  assertTrue(this._receivedChangedEvent);
182  assertTrue(this._receivedRemovedEvent);
183 
184  // Now that the events have been received, it's time to shutdown the
185  // watcher and begin phase 3.
186  this._state = STATE_PHASE3;
187  this._log(this._state + ": Starting");
188  this._fsWatcher.stopWatching(true);
189  break;
190  }
191 
192  case STATE_PHASE3:
193  {
194  // If this block is executed, something is wrong. The watcher should
195  // have reported an error during startup since the saved application
196  // data has been removed.
197  this._log(this._state +
198  ": ERROR: The session was not reported as an error!");
199  assertTrue(false);
200  this._cleanup();
201  }
202  }
203  },
204 
205  onWatcherStopped: function()
206  {
207  switch (this._state) {
208  case STATE_PHASE1:
209  {
210  this._log(this._state + ": Watcher has stopped");
211  // Now that the watcher has stopped in phase 1, it is now time to start
212  // phase 2. In phase 2, we want to create some events in the directory
213  // to ensure that they are reported once the watcher is re-initialized.
214  this._state = STATE_PHASE2;
215  this._log(this._state + ": Starting");
216 
217  // Add event:
218  this._addedFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0755);
219 
220  // Remove event:
221  this._removeFile.remove(false);
222 
223  // Changed event
224  var foStream = Cc["@mozilla.org/network/file-output-stream;1"]
225  .createInstance(Ci.nsIFileOutputStream);
226  foStream.init(this._changeFile, -1, -1, 0);
227  var junk = "garbage garbage garbage";
228  foStream.write(junk, junk.length);
229  foStream.close();
230 
231  this._log(this._state + ": File system events created.");
232 
233  // Now set the startup timer to fire in one second to re-initialize the
234  // watcher.
235  this._restartTimer.initWithCallback(this,
236  1000,
237  Ci.nsITimerCallback.TYPE_ONE_SHOT);
238  break;
239  }
240 
241  case STATE_PHASE3:
242  {
243  this._log(this._state + ": Watcher has stopped");
244  this._state = STATE_PHASE3;
245 
246  // Now set the restart timer back up
247  this._restartTimer.initWithCallback(this,
248  1000,
249  Ci.nsITimerCallback.TYPE_ONE_SHOT);
250  break;
251  }
252  }
253  },
254 
255  onWatcherError: function(aErrorType, aDescription)
256  {
257  switch (aErrorType) {
258  case Ci.sbIFileSystemListener.SESSION_LOAD_ERROR:
259  if (this._state != STATE_PHASE3) {
260  this._log(this._state +
261  ": ERROR: received session load error, unexpected!");
262  assertTrue(false);
263  }
264  else {
265  this._log("PHASE 3: Got the session load error.");
266  }
267  break;
268 
269  case Ci.sbIFileSystemListener.ROOT_PATH_MISSING:
270  doFail("ERROR: The root watch path is missing!!");
271  break;
272 
273  case Ci.sbIFileSystemListener.INVALID_DIRECTORY:
274  doFail("ERROR: Invalid directory was passed to watcher!");
275  break;
276  }
277 
278  this._cleanup();
279  },
280 
281  onFileSystemChanged: function(aFilePath)
282  {
283  this._log("CHANGED: " + aFilePath);
284  this._receivedChangedEvent = true;
285  },
286 
287  onFileSystemRemoved: function(aFilePath)
288  {
289  this._log("REMOVED: " + aFilePath);
290  this._receivedRemovedEvent = true;
291  },
292 
293  onFileSystemAdded: function(aFilePath)
294  {
295  this._log("ADDED: " + aFilePath);
296  this._receivedAddedEvent = true;
297  },
298 
299  // nsITimerCallback
300  notify: function(aTimer)
301  {
302  if (aTimer == this._restartTimer) {
303  this._log(this._state + ": Re-starting the watcher with session " +
304  this._savedSessionID);
305 
306  this._fsWatcher = null;
307  this._fsWatcher = Cc["@songbirdnest.com/filesystem/watcher;1"]
308  .createInstance(Ci.sbIFileSystemWatcher);
309 
310  // In phase 3, the session data should be removed from disk to test
311  // the error reporting API on the filesystem watcher API.
312  if (this._state == STATE_PHASE3) {
313  this._fsWatcher.deleteSession(this._savedSessionID);
314  this._log(this._state + ": Session " + this._savedSessionID +
315  " has been deleted");
316 
317  }
318 
319  this._fsWatcher.initWithSession(this._savedSessionID, this);
320  this._fsWatcher.startWatching();
321  }
322  else {
323  this._log(this._state + ": Stopping watcher.");
324  this._fsWatcher.stopWatching(true);
325  }
326  },
327 
329  XPCOMUtils.generateQI( [Ci.sbIFileSystemListener, Ci.nsITimerCallback] )
330 };
331 
const Cc
function runTest()
Advanced DataRemote unit tests.
const STATE_PHASE1
function testFinished()
sbOSDControlService prototype QueryInterface
function assertTrue(aTest, aMessage)
const STATE_PHASE2
TimerLoop prototype notify
const STATE_PHASE3
function startTest()
return null
Definition: FeedWriter.js:1143
function _log(aMsg, aMenuID)
const Ci
function doFail(text)
function sbFSListener(aWatchDir, aFSWatcher)
function testPending()