test_metadatajob_writing.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-2008 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 
31 var gTestFileLocation = "testharness/metadatamanager/files/";
32 
33 // TODO Confirm this extension list. Don't forget to update files/Makefile.in as well.
35  "mp3", "mov", "m4p", "ogm", "ogx", "tta", "wv",
36 
37 // TODO Taglib does not support video files
38 // "m4v", "ogv"
39 
40  "ogg", "flac", "mpc"
41 
42 // TODO oga and spx reading isn't working yet. Filed as bug 8768.
43 // "oga", "spx"
44 
45 // TODO Unable to write metadata for m4a files. Filed as bug 8812.
46 // "m4a"
47  ];
48 
53 function runTest() {
54  /* SETUP */
55 
56  // Make a copy of everything in the test file folder
57  // so that our changes don't interfere with other tests
58  var testFolder = getCopyOfFolder(newAppRelativeFile(gTestFileLocation), "_temp_writing_files");
59 
60  // Make a file with a unicode filename. This would be checked in, except
61  // the windows build system can't handle unicode filenames.
62  var unicodeFile = testFolder.clone();
63  unicodeFile.append("MP3_ID3v23.mp3");
64  unicodeFile = getCopyOfFile(unicodeFile, "\u2606\u2606\u2606\u2606\u2606\u2606.mp3");
65 
66  var prefSvc = Cc["@mozilla.org/preferences-service;1"]
67  .getService(Ci.nsIPrefBranch);
68  var oldWritingEnabledPref = prefSvc.getBoolPref("songbird.metadata.enableWriting");
69  prefSvc.setBoolPref("songbird.metadata.enableWriting", true);
70 
71  // Now find all the media files in our testing directory
72  var urls = getMediaFilesInFolder(testFolder);
73 
74  // Make sure we have files to test
75  assertEqual(urls.length > 0, true);
76 
78  // Import the test items //
80  var library = createNewLibrary( "test_metadatajob_writing_library" );
81  var items = importFilesToLibrary(urls, library);
82  assertEqual(items.length, urls.length);
83 
84  var job = startMetadataJob(items, "read");
85 
86  // Wait for reading to complete before continuing
87  job.addJobProgressListener(function onReadComplete(job) {
88  reportJobProgress(job, "MetadataJob_Writing - onReadComplete");
89 
90  if (job.status == Components.interfaces.sbIJobProgress.STATUS_RUNNING) {
91  return;
92  }
93  job.removeJobProgressListener(onReadComplete);
94 
96  // Save new metadata into the files //
98  var unicodeSample =
99  "\u008C\u00A2\u00FE" + // Latin-1 Sup
100  "\u141A\u142B\u1443" + // Canadian Aboriginal
101  "\u184F\u1889\u1896" + // Mongolian
102  "\u4E08\u4E02\u9FBB" + // CJK Unified Extension
103  "\u4DCA\u4DC5\u4DD9" + // Hexagram Symbols
104  "\u0308\u030F\u034F" + // Combining Diacritics
105  "\u033C\u034C\u035C" +
106  "\uD800\uDC83\uD800" + // Random Surrogate Pairs
107  "\uDC80\uD802\uDD00";
108 
109  var successValues = [
110  // test a basic value
111  [SBProperties.trackName, SBProperties.trackName],
112 
113  // and some unicode
114  [SBProperties.albumName, SBProperties.albumName + unicodeSample],
115 
116  // what about a longer one? (ID3v1 only allows 30 char.)
117  // bug <NNN>: id3v22 files are coming back truncated but not ID3v1 for some reason
118  //[SBProperties.comment,
119  // SBProperties.comment + SBProperties.comment + SBProperties.comment],
120 
121  // this is slightly thorny, because the specs allow for multiple values
122  // but our database just concats things together.
123  // we should think about this some day
124  [SBProperties.genre, SBProperties.genre],
125 
126  // make sure extended properties work
127  [SBProperties.composerName, SBProperties.composerName],
128  [SBProperties.lyricistName, SBProperties.lyricistName],
129  [SBProperties.lyrics, SBProperties.lyrics],
130 
131  // bug 9086: producer is fucked for ID3v2 -- need TIPL/IPLS
132  // and if i'm going to do that, all the other ones should check it too
133  //[SBProperties.producerName, SBProperties.producerName],
134 
135  // bug 9084: rating is fucked for ID3v2
136  //[SBProperties.rating, 3],
137 
138  // make sure track numbers work
139  [SBProperties.trackNumber, 7],
140  [SBProperties.totalTracks, 13],
141 
142  [SBProperties.discNumber, 1],
143  [SBProperties.totalDiscs, 2],
144 
145  // what about a longer one? (ID3v1 only allows 30 char.)
146  // bug 9088: id3v22 files are coming back truncated but not ID3v1 for some reason
147  //[SBProperties.comment,
148  // SBProperties.comment + SBProperties.comment + SBProperties.comment],
149 
150  // try a blank one
151  [SBProperties.artistName, null],
152 
153  // what about a partial disc number?
154  //[SBProperties.totalDiscs, 0], // TODO: reconcile 0/""/null
155  //[SBProperties.totalDiscs, 2],
156 
157  [SBProperties.year, 2004],
158 
159  [SBProperties.isPartOfCompilation, 1]
160  ];
161 
162  // List of properties we want to write
163  var propertiesToWrite = [];
164 
165  // set all mediaitems to the supplied metadata
166  for each (var item in items) {
167  for each (var pair in successValues) {
168  item.setProperty(pair[0], pair[1]);
169 
170  // Add the property name to the write list if we have not alredy done so
171  if (propertiesToWrite.indexOf(pair[0]) < 0) {
172  propertiesToWrite.push(pair[0]);
173  }
174  }
175  }
176 
177  job = startMetadataJob(items, "write", propertiesToWrite);
178 
179  // Wait for writing to complete before continuing
180  job.addJobProgressListener(function onWriteComplete(job) {
181  reportJobProgress(job, "MetadataJob_Writing - onWriteComplete");
182 
183  if (job.status == Components.interfaces.sbIJobProgress.STATUS_RUNNING) {
184  return;
185  }
186  job.removeJobProgressListener(onWriteComplete);
187 
188  // Verify job progress reporting.
189  // NOTE: Comment these out to receive more useful debug information
190  assertEqual(urls.length, job.total);
191  assertEqual(urls.length, job.progress);
192  assertEqual(0, job.errorCount);
193  assertEqual(job.status, Components.interfaces.sbIJobProgress.STATUS_SUCCEEDED);
194 
196  // Now reimport and confirm that the write went ok //
198  library.clear();
199  items = importFilesToLibrary(urls, library);
200  assertEqual(items.length, urls.length);
201  job = startMetadataJob(items, "read");
202 
203  // Wait for reading to complete before continuing
204  job.addJobProgressListener(function onSecondReadComplete(job) {
205  reportJobProgress(job, "MetadataJob_Writing - onSecondReadComplete");
206  if (job.status == Components.interfaces.sbIJobProgress.STATUS_RUNNING) {
207  return;
208  }
209  job.removeJobProgressListener(onSecondReadComplete);
210 
211  // Verify job progress reporting.
212  // NOTE: Comment these out to receive more useful debug information
213  assertEqual(urls.length, job.total);
214  assertEqual(urls.length, job.progress);
215  assertEqual(0, job.errorCount);
216  assertEqual(job.status, Components.interfaces.sbIJobProgress.STATUS_SUCCEEDED);
217 
218  var failedFiles = 0;
219  for each (var item in items) {
220  var failedProperties = 0;
221  log("MetadataJob_Write: verifying " + item.contentSrc.path);
222  for each (var pair in successValues) {
223  if (item.getProperty(pair[0]) != pair[1]) {
224 
225  // bug 9091 -- ID3v22 doesn't seem to support lyrics
226  if(item.contentSrc.path.indexOf("MP3_ID3v22.mp3") != 0) {
227  if(pair[0] == SBProperties.lyricistName || pair[0] == SBProperties.lyrics) {
228  continue;
229  }
230  }
231 
232  log("MetadataJob_Write: \n" + pair[0]+ ":\nfound:\t" + item.getProperty(pair[0])
233  + "\nwanted:\t" + pair[1]);
234  failedProperties++;
235  }
236  }
237  if (failedProperties != 0) {
238  failedFiles++;
239  }
240  }
241  assertEqual(failedFiles, 0, "Some files failed to write correctly.");
242 
243  prefSvc.setBoolPref("songbird.metadata.enableWriting", oldWritingEnabledPref);
244  // We're done, so kill all the temp files
245  testFolder.remove(true);
246  job = null;
247  testFinished();
248  });
249  });
250  });
251  testPending();
252 }
253 
254 
258 function getMediaFilesInFolder(folder) {
259  var scan = Cc["@songbirdnest.com/Songbird/FileScan;1"]
260  .createInstance(Ci.sbIFileScan);
261  var query = Cc["@songbirdnest.com/Songbird/FileScanQuery;1"]
262  .createInstance(Ci.sbIFileScanQuery);
263  query.setDirectory(folder.path);
264  query.setRecurse(true);
265 
266  for each (var extension in gSupportedFileExtensions) {
267  query.addFileExtension(extension);
268  }
269 
270  scan.submitQuery(query);
271 
272  log("Scanning...");
273 
274  while (query.isScanning()) {
275  sleep(1000);
276  }
277 
278  assertEqual(query.getFileCount() > 0, true);
279  var urls = query.getResultRangeAsURIStrings(0, query.getFileCount() - 1);
280 
281  scan.finalize();
282 
283  return urls;
284 }
285 
286 
290 function importFilesToLibrary(files, library) {
291  var items = library.batchCreateMediaItems(files, null, true);
292  assertEqual(items.length, files.length);
293  var jsItems = [];
294  for (var i = 0; i < items.length; i++) {
295  jsItems.push(items.queryElementAt(i, Ci.sbIMediaItem));
296  }
297  return jsItems;
298 }
299 
300 
304 function startMetadataJob(items, type, writeProperties) {
305  var array = Components.classes["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
306  .createInstance(Components.interfaces.nsIMutableArray);
307  for each (var item in items) {
308  array.appendElement(item, false);
309  }
310  manager = Components.classes["@songbirdnest.com/Songbird/FileMetadataService;1"]
311  .getService(Components.interfaces.sbIFileMetadataService);
312 
313  var job;
314  if (type == "write") {
315  job = manager.write(array, ArrayConverter.stringEnumerator(writeProperties));
316  } else {
317  job = manager.read(array);
318  }
319  return job;
320 }
321 
let prefSvc
function sleep(ms, suppressOutput)
const Cc
function runTest()
Advanced DataRemote unit tests.
function newAppRelativeFile(path)
function startMetadataJob(items, type, writeProperties)
var testFolder
inArray array
function onReadComplete(job)
function log(s)
function testFinished()
function createNewLibrary(databaseGuid, databaseLocation)
function getMediaFilesInFolder(folder)
var gSupportedFileExtensions
function assertEqual(aExpected, aActual, aMessage)
function importFilesToLibrary(files, library)
function reportJobProgress(job, jobName)
function getCopyOfFile(file, tempName, optionalLocation)
return null
Definition: FeedWriter.js:1143
const Ci
function getCopyOfFolder(folder, tempName)
Copy the given folder to tempName, returning an nsIFile for the new location.
function onWriteComplete(job)
_getSelectedPageStyle s i
var gTestFileLocation
Test creation and execution of metadata writing jobs.
function testPending()