Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
178
gaia/apps/music/test/unit/metadata/album_art_test.js
Executable file
178
gaia/apps/music/test/unit/metadata/album_art_test.js
Executable file
|
|
@ -0,0 +1,178 @@
|
|||
/* global AlbumArt, MockFileStore, MockGetDeviceStorage, pass, fail,
|
||||
suite, setup, teardown, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/test/unit/metadata/mock_navigator_getdevicestorage.js');
|
||||
|
||||
suite('album art', function() {
|
||||
|
||||
var RealGetDeviceStorage;
|
||||
|
||||
setup(function(done) {
|
||||
RealGetDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockGetDeviceStorage;
|
||||
|
||||
require('/js/metadata/album_art.js', function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
navigator.getDeviceStorage = RealGetDeviceStorage;
|
||||
});
|
||||
|
||||
var songBlob = new Blob();
|
||||
songBlob.name = '/path/to/file.mp3';
|
||||
|
||||
test('embedded art', function(done) {
|
||||
var metadata = {
|
||||
picture: { flavor: 'embedded' }
|
||||
};
|
||||
|
||||
AlbumArt.process(songBlob, metadata)
|
||||
.then(function(metadata) {
|
||||
// Make sure we didn't do anything to the metadata.
|
||||
assert.deepEqual(metadata, {
|
||||
picture: { flavor: 'embedded' }
|
||||
});
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('unsynced art', function(done) {
|
||||
var imageData = 'an image';
|
||||
var metadata = {
|
||||
artist: 'artist',
|
||||
album: 'album',
|
||||
picture: {
|
||||
flavor: 'unsynced',
|
||||
blob: new Blob([imageData], {type: 'image/jpeg'})
|
||||
}
|
||||
};
|
||||
var pictureFilename = '/path/.music/covers/' + metadata.artist + '.' +
|
||||
metadata.album + '.' + imageData.length + '.jpg';
|
||||
|
||||
AlbumArt.process(songBlob, metadata)
|
||||
.then(function(metadata) {
|
||||
assert.deepEqual(metadata, {
|
||||
artist: 'artist',
|
||||
album: 'album',
|
||||
picture: { flavor: 'unsynced', filename: pictureFilename }
|
||||
});
|
||||
|
||||
return MockFileStore.readAsText('pictures', pictureFilename);
|
||||
})
|
||||
.then(function(text) {
|
||||
assert.strictEqual(imageData, text);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('unsynced art (no artist/album)', function(done) {
|
||||
var imageData = 'an image';
|
||||
var metadata = {
|
||||
picture: {
|
||||
flavor: 'unsynced',
|
||||
blob: new Blob([imageData], {type: 'image/jpeg'})
|
||||
}
|
||||
};
|
||||
var pictureFilename = '/path/.music/covers/_path_to_file.mp3.' +
|
||||
imageData.length + '.jpg';
|
||||
|
||||
AlbumArt.process(songBlob, metadata)
|
||||
.then(function(metadata) {
|
||||
assert.deepEqual(metadata, {
|
||||
picture: { flavor: 'unsynced', filename: pictureFilename }
|
||||
});
|
||||
|
||||
return MockFileStore.readAsText('pictures', pictureFilename);
|
||||
})
|
||||
.then(function(text) {
|
||||
assert.strictEqual(imageData, text);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('unsynced art (already stored)', function(done) {
|
||||
// These should be the same length!
|
||||
var oldImageData = 'an image';
|
||||
var newImageData = 'diffdata';
|
||||
|
||||
var metadata = {
|
||||
artist: 'artist',
|
||||
album: 'album',
|
||||
picture: {
|
||||
flavor: 'unsynced',
|
||||
blob: new Blob([newImageData], {type: 'image/jpeg'})
|
||||
}
|
||||
};
|
||||
var pictureFilename = '/path/.music/covers/' + metadata.artist + '.' +
|
||||
metadata.album + '.' + newImageData.length + '.jpg';
|
||||
|
||||
// Inject an existing image with slightly different data so we can tell
|
||||
// it from the metadata's "new" image.
|
||||
MockFileStore.set('pictures', pictureFilename, new Blob(
|
||||
[oldImageData], {type: 'image/jpeg'}
|
||||
));
|
||||
|
||||
AlbumArt.process(songBlob, metadata)
|
||||
.then(function(metadata) {
|
||||
assert.deepEqual(metadata, {
|
||||
artist: 'artist',
|
||||
album: 'album',
|
||||
picture: { flavor: 'unsynced', filename: pictureFilename }
|
||||
});
|
||||
|
||||
return MockFileStore.readAsText('pictures', pictureFilename);
|
||||
})
|
||||
.then(function(text) {
|
||||
assert.strictEqual(oldImageData, text);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('external art', function(done) {
|
||||
var imageData = 'an image';
|
||||
var pictureFilename = '/path/to/cover.jpg';
|
||||
// Inject an external image into the same folder as our "file".
|
||||
MockFileStore.set('pictures', pictureFilename, new Blob(
|
||||
[imageData], {type: 'image/jpeg'}
|
||||
));
|
||||
|
||||
var metadata = {};
|
||||
|
||||
AlbumArt.process(songBlob, metadata)
|
||||
.then(function(metadata) {
|
||||
// Make sure we found the external cover art.
|
||||
assert.deepEqual(metadata, {
|
||||
picture: { flavor: 'external', filename: pictureFilename }
|
||||
});
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('no art', function(done) {
|
||||
var metadata = {};
|
||||
songBlob.name = '/another/path/to/file.mp3';
|
||||
|
||||
AlbumArt.process(songBlob, metadata)
|
||||
.then(function(metadata) {
|
||||
// Make sure we didn't do anything to the metadata.
|
||||
assert.deepEqual(metadata, {});
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('temporary file', function(done) {
|
||||
var metadata = {};
|
||||
|
||||
AlbumArt.process(new Blob(), metadata)
|
||||
.then(function(metadata) {
|
||||
// Make sure we didn't do anything to the metadata.
|
||||
assert.deepEqual(metadata, {});
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
92
gaia/apps/music/test/unit/metadata/core_test.js
Executable file
92
gaia/apps/music/test/unit/metadata/core_test.js
Executable file
|
|
@ -0,0 +1,92 @@
|
|||
/* global AudioMetadata, fetchBuffer, MockLazyLoader, readBlob,
|
||||
assertBuffersEqual, pass, fail, suite, setup, teardown,
|
||||
test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/shared/js/omadrm/fl.js');
|
||||
require('/js/metadata/forward_lock.js');
|
||||
require('/js/metadata/id3v1.js');
|
||||
require('/js/metadata/id3v2.js');
|
||||
require('/js/metadata/ogg.js');
|
||||
require('/js/metadata/vorbis_picture.js');
|
||||
|
||||
suite('core metadata parsing', function() {
|
||||
|
||||
var RealLazyLoader, expectedPicture;
|
||||
|
||||
setup(function(done) {
|
||||
RealLazyLoader = window.LazyLoader;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
|
||||
require('/js/metadata/core.js')
|
||||
.then(function() {
|
||||
return fetchBuffer('/test-data/album-art.jpg');
|
||||
})
|
||||
.then(function(data) {
|
||||
expectedPicture = data;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.LazyLoader = RealLazyLoader;
|
||||
});
|
||||
|
||||
test('3gp video rejected', function(done) {
|
||||
var blob = new Blob([new Uint8Array(256)]);
|
||||
blob.name = 'DCIM/video.3gp';
|
||||
AudioMetadata.parse(blob)
|
||||
.then(fail(done, '3gp video wasn\'t rejected'), pass(done));
|
||||
});
|
||||
|
||||
test('small file rejected', function(done) {
|
||||
var blob = new Blob([]);
|
||||
AudioMetadata.parse(blob)
|
||||
.then(fail(done, 'small file wasn\'t rejected'), pass(done));
|
||||
});
|
||||
|
||||
test('ordinary file', function(done) {
|
||||
fetchBuffer('/test-data/vorbis-c.ogg')
|
||||
.then(function(data) {
|
||||
return AudioMetadata.parse(new Blob([data]));
|
||||
})
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'vorbis');
|
||||
assert.strictEqual(metadata.artist, 'Angra');
|
||||
assert.strictEqual(metadata.album, 'Holy Land');
|
||||
assert.strictEqual(metadata.title, 'Carolina IV');
|
||||
assert.strictEqual(metadata.tracknum, 4);
|
||||
assert.strictEqual(metadata.trackcount, 10);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
assert.strictEqual(metadata.picture.flavor, 'unsynced');
|
||||
assert.strictEqual(metadata.picture.blob.type, 'image/jpeg');
|
||||
|
||||
return readBlob(metadata.picture.blob);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('no metadata', function(done) {
|
||||
var filename = '/test-data/no-tag.mp3';
|
||||
fetchBuffer(filename)
|
||||
.then(function(buffer) {
|
||||
var blob = new Blob([buffer]);
|
||||
blob.name = filename;
|
||||
return blob;
|
||||
})
|
||||
.then(AudioMetadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, undefined);
|
||||
assert.strictEqual(metadata.artist, '');
|
||||
assert.strictEqual(metadata.album, '');
|
||||
assert.strictEqual(metadata.title, 'no-tag');
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
55
gaia/apps/music/test/unit/metadata/flac_test.js
Executable file
55
gaia/apps/music/test/unit/metadata/flac_test.js
Executable file
|
|
@ -0,0 +1,55 @@
|
|||
/* global FLACMetadata, fetchBuffer, makeBlobView, MockLazyLoader,
|
||||
readPicSlice, assertBuffersEqual, pass, fail, suite, setup,
|
||||
teardown, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/js/metadata/flac.js');
|
||||
require('/js/metadata/vorbis_picture.js');
|
||||
|
||||
suite('flac tags', function() {
|
||||
var RealLazyLoader;
|
||||
|
||||
var expectedPicture;
|
||||
setup(function(done) {
|
||||
RealLazyLoader = window.LazyLoader;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
|
||||
fetchBuffer('/test-data/album-art.jpg').then(function(buffer) {
|
||||
expectedPicture = buffer;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.LazyLoader = RealLazyLoader;
|
||||
});
|
||||
|
||||
test('vorbis comment', function(done) {
|
||||
var blob;
|
||||
fetchBuffer('/test-data/vorbis-c.flac')
|
||||
.then(function(buffer) {
|
||||
return (blob = new Blob([buffer]));
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(FLACMetadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'flac');
|
||||
assert.strictEqual(metadata.artist, 'Black Sabbath');
|
||||
assert.strictEqual(metadata.album, 'Master of Reality');
|
||||
assert.strictEqual(metadata.title, 'Children of the Grave');
|
||||
assert.strictEqual(metadata.tracknum, 4);
|
||||
assert.strictEqual(metadata.trackcount, 8);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
assert.strictEqual(metadata.picture.flavor, 'embedded');
|
||||
assert.strictEqual(metadata.picture.type, 'image/jpeg');
|
||||
|
||||
return readPicSlice(blob, metadata.picture);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
59
gaia/apps/music/test/unit/metadata/formats_test.js
Executable file
59
gaia/apps/music/test/unit/metadata/formats_test.js
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
/* global FLACMetadata, ForwardLockMetadata, ID3v1Metadata, ID3v2Metadata,
|
||||
MP4Metadata, OggMetadata, MetadataFormats, fetchBlobView, fetchBuffer,
|
||||
ForwardLock, makeBlobView, pass, fail, suite, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/shared/js/omadrm/fl.js');
|
||||
require('/js/metadata/flac.js');
|
||||
require('/js/metadata/forward_lock.js');
|
||||
require('/js/metadata/id3v1.js');
|
||||
require('/js/metadata/id3v2.js');
|
||||
require('/js/metadata/mp4.js');
|
||||
require('/js/metadata/ogg.js');
|
||||
|
||||
suite('format deduction', function() {
|
||||
// Define the tests we want to run; note that `module` is a getter because
|
||||
// the modules won't be loaded by the time this code is run.
|
||||
var formats = [
|
||||
{name: 'flac', file: '/test-data/vorbis-c.flac',
|
||||
get module() { return FLACMetadata; }},
|
||||
{name: 'mp3 (id3v1)', file: '/test-data/id3v1-simple.mp3',
|
||||
get module() { return ID3v1Metadata; }},
|
||||
{name: 'mp3 (id3v2)', file: '/test-data/id3v2.4-simple-latin1.mp3',
|
||||
get module() { return ID3v2Metadata; }},
|
||||
{name: 'mp3 (id3v1+2)', file: '/test-data/id3v1+2-simple.mp3',
|
||||
get module() { return ID3v2Metadata; }},
|
||||
{name: 'flac', file: '/test-data/aac-tags.m4a',
|
||||
get module() { return MP4Metadata; }},
|
||||
{name: 'ogg', file: '/test-data/vorbis-c.ogg',
|
||||
get module() { return OggMetadata; }},
|
||||
];
|
||||
|
||||
formats.forEach(function(fmt) {
|
||||
test(fmt.name, function(done) {
|
||||
fetchBlobView(fmt.file)
|
||||
.then(MetadataFormats.findParser)
|
||||
.then(function(parser) {
|
||||
assert.strictEqual(parser._formatInfo.module, fmt.module);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
test('forwardlock', function(done) {
|
||||
fetchBuffer('/test-data/no-tag.mp3')
|
||||
.then(function(buffer) {
|
||||
return ForwardLock.lockBuffer(
|
||||
0xDEADBEEF, buffer, 'audio/mpeg', {}
|
||||
);
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(MetadataFormats.findParser)
|
||||
.then(function(parser) {
|
||||
assert.strictEqual(parser._formatInfo.module, ForwardLockMetadata);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
157
gaia/apps/music/test/unit/metadata/forward_lock_test.js
Executable file
157
gaia/apps/music/test/unit/metadata/forward_lock_test.js
Executable file
|
|
@ -0,0 +1,157 @@
|
|||
/* global ForwardLockMetadata, fetchBuffer, ForwardLock, makeBlobView,
|
||||
MockGetDeviceStorage, MockLazyLoader, readBlob, assertBuffersEqual,
|
||||
pass, fail, suite, setup, teardown, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/shared/test/unit/mocks/mock_navigator_getdevicestorage.js');
|
||||
require('/shared/js/omadrm/fl.js');
|
||||
require('/js/metadata/forward_lock.js');
|
||||
require('/js/metadata/id3v1.js');
|
||||
require('/js/metadata/id3v2.js');
|
||||
|
||||
suite('forwardlock files', function() {
|
||||
|
||||
var RealLazyLoader, RealGetDeviceStorage, RealForwardLockGetKey;
|
||||
|
||||
var secret = 0xDEADBEEF;
|
||||
function mockGetKey(secret, callback) {
|
||||
callback(secret);
|
||||
}
|
||||
|
||||
setup(function(done) {
|
||||
RealLazyLoader = window.LazyLoader;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
|
||||
RealGetDeviceStorage = navigator.getDeviceStorage;
|
||||
navigator.getDeviceStorage = MockGetDeviceStorage;
|
||||
|
||||
RealForwardLockGetKey = ForwardLock.getKey;
|
||||
ForwardLock.getKey = mockGetKey.bind(this, secret);
|
||||
|
||||
require('/js/metadata/core.js', function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.LazyLoader = RealLazyLoader;
|
||||
navigator.getDeviceStorage = RealGetDeviceStorage;
|
||||
ForwardLock.getKey = RealForwardLockGetKey;
|
||||
});
|
||||
|
||||
test('mp3 with id3v2 tag', function(done) {
|
||||
var vendorMetadata = {vendor: 'Songs for Cool Kids, Inc'};
|
||||
fetchBuffer('/test-data/id3v2.4-simple-latin1.mp3')
|
||||
.then(function(buffer) {
|
||||
return ForwardLock.lockBuffer(
|
||||
secret, buffer, 'audio/mpeg', vendorMetadata
|
||||
);
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(ForwardLockMetadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.locked, true);
|
||||
assert.strictEqual(metadata.vendor, vendorMetadata.vendor);
|
||||
assert.strictEqual(metadata.tag_format, 'id3v2.4.0');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('mp3 with no metadata', function(done) {
|
||||
var vendorMetadata = {vendor: 'Songs for Cool Kids, Inc',
|
||||
name: 'The Song That Never Ends'};
|
||||
fetchBuffer('/test-data/no-tag.mp3')
|
||||
.then(function(buffer) {
|
||||
return ForwardLock.lockBuffer(
|
||||
secret, buffer, 'audio/mpeg', vendorMetadata
|
||||
);
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(ForwardLockMetadata.parse)
|
||||
.then(function(metadata) {
|
||||
done(function() {
|
||||
assert.strictEqual(metadata.locked, true);
|
||||
assert.strictEqual(metadata.vendor, vendorMetadata.vendor);
|
||||
assert.strictEqual(metadata.artist, '');
|
||||
assert.strictEqual(metadata.album, '');
|
||||
assert.strictEqual(metadata.title, vendorMetadata.name);
|
||||
});
|
||||
}).catch(done);
|
||||
});
|
||||
|
||||
test('decrypting forwardlock with no secret key', function(done) {
|
||||
fetchBuffer('/test-data/id3v2.4-simple-latin1.mp3')
|
||||
.then(function(buffer) {
|
||||
return ForwardLock.lockBuffer(
|
||||
secret, buffer, 'audio/mpeg', {vendor: 'vendor'}
|
||||
);
|
||||
})
|
||||
.then(function(blob) {
|
||||
ForwardLock.getKey = mockGetKey.bind(this, null);
|
||||
return blob;
|
||||
})
|
||||
.catch(function(err) {
|
||||
// Make sure we haven't hit an error yet...
|
||||
done(new Error('failed to encrypt our test file'));
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(ForwardLockMetadata.parse)
|
||||
.then(fail(done, 'parsing should have failed, but passed'), pass(done));
|
||||
});
|
||||
|
||||
suite('album art', function() {
|
||||
var expectedPicture;
|
||||
setup(function(done) {
|
||||
fetchBuffer('/test-data/album-art.jpg').then(function(buffer) {
|
||||
expectedPicture = buffer;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
var testInfo = [
|
||||
{test: 'mp3 with non-unsynced album art',
|
||||
filename: '/test-data/id3v2.4-picture.mp3'},
|
||||
{test: 'mp3 with unsynced album art',
|
||||
filename: '/test-data/id3v2.4-framesunsync.mp3'},
|
||||
];
|
||||
testInfo.forEach(function(info) {
|
||||
test(info.test, function(done) {
|
||||
var vendorMetadata = {vendor: 'Songs for Cool Kids, Inc'}, blob;
|
||||
fetchBuffer(info.filename)
|
||||
.then(function(buffer) {
|
||||
return (blob = ForwardLock.lockBuffer(
|
||||
secret, buffer, 'audio/mpeg', vendorMetadata
|
||||
));
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(ForwardLockMetadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.locked, true);
|
||||
assert.strictEqual(metadata.vendor, vendorMetadata.vendor);
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.picture.flavor, 'unsynced');
|
||||
assert.strictEqual(metadata.picture.blob.type, 'image/jpeg');
|
||||
|
||||
return readBlob(metadata.picture.blob);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
32
gaia/apps/music/test/unit/metadata/id3v1_test.js
Executable file
32
gaia/apps/music/test/unit/metadata/id3v1_test.js
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
/* global ID3v1Metadata, fetchBlobView, pass, fail, suite, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/js/metadata/id3v1.js');
|
||||
|
||||
suite('id3v1 tags', function() {
|
||||
|
||||
test('id3v1', function(done) {
|
||||
fetchBlobView('/test-data/id3v1-simple.mp3')
|
||||
.then(ID3v1Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'id3v1');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, undefined);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('no metadata', function(done) {
|
||||
fetchBlobView('/test-data/no-tag.mp3')
|
||||
.then(ID3v1Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.deepEqual(metadata, {});
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
389
gaia/apps/music/test/unit/metadata/id3v2_test.js
Executable file
389
gaia/apps/music/test/unit/metadata/id3v2_test.js
Executable file
|
|
@ -0,0 +1,389 @@
|
|||
/* global ID3v2Metadata, fetchBlobView, fetchBuffer, makeBlobView,
|
||||
MockLazyLoader, readBlob, readPicSlice, assertBuffersEqual,
|
||||
pass, fail, suite, setup, teardown, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/js/metadata/id3v1.js');
|
||||
require('/js/metadata/id3v2.js');
|
||||
|
||||
suite('id3v2 tags', function() {
|
||||
|
||||
// We have a bunch of otherwise-identical mp3 files using different ID3
|
||||
// versions, covering all valid character encodings. Test them all.
|
||||
[2, 3, 4].forEach(function(version) {
|
||||
var tag_format = 'id3v2.' + version + '.0';
|
||||
suite('simple id3v2.' + version, function() {
|
||||
|
||||
test('latin1', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version + '-simple-latin1.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, tag_format);
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('utf16', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version + '-simple-utf16.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, tag_format);
|
||||
assert.strictEqual(metadata.artist, 'Mötley Crüe');
|
||||
assert.strictEqual(metadata.album, 'Dr. Feelgood');
|
||||
assert.strictEqual(metadata.title, 'Kickstart My Heart');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 11);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
if (version === 4) {
|
||||
test('utf16be', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version + '-simple-utf16be.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, tag_format);
|
||||
assert.strictEqual(metadata.artist, 'Gåte');
|
||||
assert.strictEqual(metadata.album, 'Jygri');
|
||||
assert.strictEqual(metadata.title, 'Bruremarsj frå Jämtland');
|
||||
assert.strictEqual(metadata.tracknum, 8);
|
||||
assert.strictEqual(metadata.trackcount, 12);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('utf8', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version + '-simple-utf8.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, tag_format);
|
||||
assert.strictEqual(metadata.artist, 'Lunar Aurora');
|
||||
assert.strictEqual(metadata.album, 'Hoagascht');
|
||||
assert.strictEqual(metadata.title, 'Håbergoaß');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 8);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('simple id3v1+2', function() {
|
||||
|
||||
test('id3v1+2', function(done) {
|
||||
var filename = '/test-data/id3v1+2-simple.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
// Here we should have the v2 tag content.
|
||||
assert.strictEqual(metadata.tag_format, 'id3v2.3.0');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, undefined);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('album art', function() {
|
||||
|
||||
var expectedPicture;
|
||||
setup(function(done) {
|
||||
fetchBuffer('/test-data/album-art.jpg').then(function(buffer) {
|
||||
expectedPicture = buffer;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
[2, 3, 4].forEach(function(version) {
|
||||
test('id3v2.' + version, function(done) {
|
||||
var blob, filename = '/test-data/id3v2.' + version + '-picture.mp3';
|
||||
fetchBuffer(filename)
|
||||
.then(function(buffer) {
|
||||
return (blob = new Blob([buffer]));
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.picture.flavor, 'embedded');
|
||||
assert.strictEqual(metadata.picture.type, 'image/jpeg');
|
||||
|
||||
return readPicSlice(blob, metadata.picture);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
test('id3v2.4 with utf-16 and odd size', function(done) {
|
||||
var blob, filename = '/test-data/id3v2.4-picture-utf16-odd-size.mp3';
|
||||
fetchBuffer(filename)
|
||||
.then(function(buffer) {
|
||||
return (blob = new Blob([buffer]));
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.picture.flavor, 'embedded');
|
||||
assert.strictEqual(metadata.picture.type, 'image/jpeg');
|
||||
|
||||
return readPicSlice(blob, metadata.picture);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
var pic = new TextEncoder('utf-8').encode('odd number of bytes');
|
||||
assertBuffersEqual(buffer, pic);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('extended header', function() {
|
||||
|
||||
[3, 4].forEach(function(version) {
|
||||
var tag_format = 'id3v2.' + version + '.0';
|
||||
|
||||
test('id3v2.' + version, function(done) {
|
||||
var filename = '/test-data/id3v2.' + version + '-extheader.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, tag_format);
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('unsynchronized data', function() {
|
||||
|
||||
var expectedPicture;
|
||||
setup(function(done) {
|
||||
fetchBuffer('/test-data/album-art.jpg').then(function(buffer) {
|
||||
expectedPicture = buffer;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
[3, 4].forEach(function(version) {
|
||||
var tag_format = 'id3v2.' + version + '.0';
|
||||
|
||||
test('id3v2.' + version + ' whole tag', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version + '-allunsync.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, tag_format);
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
assert.strictEqual(metadata.picture.flavor, 'unsynced');
|
||||
assert.strictEqual(metadata.picture.blob.type, 'image/jpeg');
|
||||
|
||||
return readBlob(metadata.picture.blob);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
test('id3v2.4 selected frames', function(done) {
|
||||
var filename = '/test-data/id3v2.4-framesunsync.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'id3v2.4.0');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
assert.strictEqual(metadata.picture.flavor, 'unsynced');
|
||||
assert.strictEqual(metadata.picture.blob.type, 'image/jpeg');
|
||||
|
||||
return readBlob(metadata.picture.blob);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('id3v2.4 selected frames with data length indicator', function(done) {
|
||||
var filename = '/test-data/id3v2.4-framesunsync-datalen.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'id3v2.4.0');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
assert.strictEqual(metadata.picture.flavor, 'unsynced');
|
||||
assert.strictEqual(metadata.picture.blob.type, 'image/jpeg');
|
||||
|
||||
return readBlob(metadata.picture.blob);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
suite('multivalue frames', function() {
|
||||
|
||||
['latin1', 'utf16', 'utf16be', 'utf8'].forEach(function(encoding) {
|
||||
test('id3v2.4 ' + encoding, function(done) {
|
||||
var filename = '/test-data/id3v2.4-multivalue-' + encoding + '.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'id3v2.4.0');
|
||||
assert.strictEqual(metadata.artist, 'Dynatron / Perturbator');
|
||||
assert.strictEqual(metadata.album, 'I Am the Night');
|
||||
assert.strictEqual(metadata.title, 'Volcanic Machinery');
|
||||
assert.strictEqual(metadata.tracknum, 13);
|
||||
assert.strictEqual(metadata.trackcount, 15);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
suite('invalid files', function() {
|
||||
var RealLazyLoader;
|
||||
|
||||
setup(function() {
|
||||
RealLazyLoader = window.LazyLoader;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.LazyLoader = RealLazyLoader;
|
||||
});
|
||||
|
||||
[2, 3, 4].forEach(function(version) {
|
||||
suite('invalid id3v2.' + version, function() {
|
||||
|
||||
test('invalid frame size', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version +
|
||||
'-invalid-frame-size.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, undefined);
|
||||
assert.strictEqual(metadata.artist, undefined);
|
||||
assert.strictEqual(metadata.album, undefined);
|
||||
assert.strictEqual(metadata.title, undefined);
|
||||
assert.strictEqual(metadata.tracknum, undefined);
|
||||
assert.strictEqual(metadata.trackcount, undefined);
|
||||
assert.strictEqual(metadata.discnum, undefined);
|
||||
assert.strictEqual(metadata.disccount, undefined);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
test('invalid skipped frame', function(done) {
|
||||
var filename = '/test-data/id3v2.' + version +
|
||||
'-invalid-skipped-frame-size.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, undefined);
|
||||
assert.strictEqual(metadata.artist, undefined);
|
||||
assert.strictEqual(metadata.album, undefined);
|
||||
assert.strictEqual(metadata.title, undefined);
|
||||
assert.strictEqual(metadata.tracknum, undefined);
|
||||
assert.strictEqual(metadata.trackcount, undefined);
|
||||
assert.strictEqual(metadata.discnum, undefined);
|
||||
assert.strictEqual(metadata.disccount, undefined);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
if (version === 4) {
|
||||
test('invalid utf8', function(done) {
|
||||
var filename = '/test-data/id3v2.4-invalid-utf8.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'id3v2.4.0');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC\uFFFD');
|
||||
assert.strictEqual(metadata.album,
|
||||
'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, 9);
|
||||
assert.strictEqual(metadata.discnum, undefined);
|
||||
assert.strictEqual(metadata.disccount, undefined);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('id3v1+2 with invalid ID3v2 frame size', function(done) {
|
||||
var filename = '/test-data/id3v1+2-invalid-frame-size.mp3';
|
||||
fetchBlobView(filename)
|
||||
.then(ID3v2Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
// Here we should have the v1 tag content.
|
||||
assert.strictEqual(metadata.tag_format, 'id3v1');
|
||||
assert.strictEqual(metadata.artist, 'AC/DC');
|
||||
assert.strictEqual(metadata.album, 'Dirty Deeds Done Dirt Cheap');
|
||||
assert.strictEqual(metadata.title, 'Problem Child OLD');
|
||||
assert.strictEqual(metadata.tracknum, 5);
|
||||
assert.strictEqual(metadata.trackcount, undefined);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
12
gaia/apps/music/test/unit/metadata/mock_album_art_cache.js
Executable file
12
gaia/apps/music/test/unit/metadata/mock_album_art_cache.js
Executable file
|
|
@ -0,0 +1,12 @@
|
|||
/* exported MockAlbumArtCache */
|
||||
'use strict';
|
||||
|
||||
|
||||
var MockAlbumArtCache = {
|
||||
getThumbnailURL: function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
getThumbnailBlob: function() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
90
gaia/apps/music/test/unit/metadata/mock_navigator_getdevicestorage.js
Executable file
90
gaia/apps/music/test/unit/metadata/mock_navigator_getdevicestorage.js
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
'use strict';
|
||||
/* globals MockDOMRequest */
|
||||
/* exported MockGetDeviceStorage */
|
||||
|
||||
var MockFileStore = {
|
||||
_data: {},
|
||||
|
||||
get: function(store, filename) {
|
||||
if (this._data[store]) {
|
||||
return this._data[store][filename];
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
|
||||
set: function(store, filename, data) {
|
||||
if (!(store in this._data)) {
|
||||
this._data[store] = {};
|
||||
}
|
||||
this._data[store][filename] = data;
|
||||
},
|
||||
|
||||
readAsText: function(store, filename) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var reader = new FileReader();
|
||||
reader.readAsText(self.get(store, filename));
|
||||
reader.onload = function() {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.onerror = function() {
|
||||
reject(reader.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var MockGetDeviceStorage = function(store) {
|
||||
return {
|
||||
get: function(filename) {
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
if (MockFileStore.get(store, filename)) {
|
||||
cb.call(this);
|
||||
}
|
||||
},
|
||||
set onerror(cb) {
|
||||
if (!MockFileStore.get(store, filename)) {
|
||||
cb.call(this);
|
||||
}
|
||||
},
|
||||
get result() {
|
||||
return MockFileStore.get(store, filename);
|
||||
}
|
||||
};
|
||||
},
|
||||
addNamed: function(blob, filename) {
|
||||
var file = new Blob([blob], {type: blob.type});
|
||||
file.name = filename;
|
||||
MockFileStore.set(store, filename, file);
|
||||
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
cb({ target: {result: filename} });
|
||||
}
|
||||
};
|
||||
},
|
||||
addEventListener: function() {
|
||||
// Do nothing
|
||||
},
|
||||
available: function() {
|
||||
return {
|
||||
set onsuccess(cb) {
|
||||
setTimeout(cb);
|
||||
},
|
||||
get result() {
|
||||
return 'available';
|
||||
}
|
||||
};
|
||||
},
|
||||
// need include libraries to test following domrequest functions
|
||||
// * /shared/test/unit/mocks/mock_event_target.js
|
||||
// * /shared/test/unit/mocks/mock_dom_request.js
|
||||
freeSpace: function freeSpace() {
|
||||
return new MockDOMRequest();
|
||||
},
|
||||
usedSpace: function usedSpace() {
|
||||
return new MockDOMRequest();
|
||||
}
|
||||
};
|
||||
};
|
||||
45
gaia/apps/music/test/unit/metadata/mp4_test.js
Executable file
45
gaia/apps/music/test/unit/metadata/mp4_test.js
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
/* global MP4Metadata, fetchBuffer, makeBlobView, readPicSlice,
|
||||
assertBuffersEqual, pass, fail, suite, setup, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/js/metadata/mp4.js');
|
||||
|
||||
suite('mp4', function () {
|
||||
var expectedPicture;
|
||||
setup(function(done) {
|
||||
fetchBuffer('/test-data/album-art.jpg').then(function(buffer) {
|
||||
expectedPicture = buffer;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('m4a tags', function(done) {
|
||||
var blob;
|
||||
fetchBuffer('/test-data/aac-tags.m4a')
|
||||
.then(function(buffer) {
|
||||
return (blob = new Blob([buffer]));
|
||||
})
|
||||
.then(makeBlobView)
|
||||
.then(MP4Metadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'mp4');
|
||||
assert.strictEqual(metadata.artist, 'The Tragically Hip');
|
||||
assert.strictEqual(metadata.album, 'Trouble At The Henhouse');
|
||||
assert.strictEqual(metadata.title, 'Giftshop');
|
||||
assert.strictEqual(metadata.tracknum, 1);
|
||||
assert.strictEqual(metadata.trackcount, 12);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
assert.strictEqual(metadata.picture.flavor, 'embedded');
|
||||
assert.strictEqual(metadata.picture.type, 'image/jpeg');
|
||||
|
||||
return readPicSlice(blob, metadata.picture);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
|
||||
});
|
||||
50
gaia/apps/music/test/unit/metadata/ogg_test.js
Executable file
50
gaia/apps/music/test/unit/metadata/ogg_test.js
Executable file
|
|
@ -0,0 +1,50 @@
|
|||
/* global OggMetadata, fetchBlobView, fetchBuffer, MockLazyLoader,
|
||||
readBlob, assertBuffersEqual, pass, fail, suite, setup,
|
||||
teardown, test, assert */
|
||||
'use strict';
|
||||
|
||||
require('/test/unit/metadata/utils.js');
|
||||
require('/js/metadata/ogg.js');
|
||||
require('/js/metadata/vorbis_picture.js');
|
||||
|
||||
suite('ogg tags', function() {
|
||||
var RealLazyLoader;
|
||||
var expectedPicture;
|
||||
|
||||
setup(function(done) {
|
||||
RealLazyLoader = window.LazyLoader;
|
||||
window.LazyLoader = MockLazyLoader;
|
||||
|
||||
fetchBuffer('/test-data/album-art.jpg').then(function(buffer) {
|
||||
expectedPicture = buffer;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
teardown(function() {
|
||||
window.LazyLoader = RealLazyLoader;
|
||||
});
|
||||
|
||||
test('vorbis comment', function(done) {
|
||||
fetchBlobView('/test-data/vorbis-c.ogg')
|
||||
.then(OggMetadata.parse)
|
||||
.then(function(metadata) {
|
||||
assert.strictEqual(metadata.tag_format, 'vorbis');
|
||||
assert.strictEqual(metadata.artist, 'Angra');
|
||||
assert.strictEqual(metadata.album, 'Holy Land');
|
||||
assert.strictEqual(metadata.title, 'Carolina IV');
|
||||
assert.strictEqual(metadata.tracknum, 4);
|
||||
assert.strictEqual(metadata.trackcount, 10);
|
||||
assert.strictEqual(metadata.discnum, 1);
|
||||
assert.strictEqual(metadata.disccount, 1);
|
||||
assert.strictEqual(metadata.picture.flavor, 'unsynced');
|
||||
assert.strictEqual(metadata.picture.blob.type, 'image/jpeg');
|
||||
|
||||
return readBlob(metadata.picture.blob);
|
||||
})
|
||||
.then(function(buffer) {
|
||||
assertBuffersEqual(buffer, expectedPicture);
|
||||
})
|
||||
.then(pass(done), fail(done));
|
||||
});
|
||||
});
|
||||
83
gaia/apps/music/test/unit/metadata/utils.js
Executable file
83
gaia/apps/music/test/unit/metadata/utils.js
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
/* global BlobView, assert */
|
||||
/* exported fetchBlobView, fetchBuffer, readPicSlice, assertBuffersEqual, pass,
|
||||
fail */
|
||||
|
||||
'use strict';
|
||||
|
||||
require('/shared/js/blobview.js');
|
||||
require('/js/metadata/formats.js');
|
||||
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
||||
|
||||
function pass(done) {
|
||||
return function() { done(); };
|
||||
}
|
||||
|
||||
function fail(done, desc) {
|
||||
if (!desc) {
|
||||
desc = 'unknown error';
|
||||
}
|
||||
return function(err) { done(err || new Error(desc)); };
|
||||
}
|
||||
|
||||
function fetchBuffer(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.onload = function() {
|
||||
if (xhr.status !== 200) {
|
||||
reject(new Error('Failed with status: ' + xhr.status));
|
||||
} else {
|
||||
resolve(this.response);
|
||||
}
|
||||
};
|
||||
xhr.onerror = xhr.ontimeout = function() {
|
||||
reject(new Error('Failed'));
|
||||
};
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
function makeBlobView(blob, size) {
|
||||
if (size === undefined) {
|
||||
size = 64 * 1024;
|
||||
}
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
BlobView.get(blob, 0, size, function(blobview, error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(blobview);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fetchBlobView(url, size) {
|
||||
return fetchBuffer(url).then(function(buffer) {
|
||||
return makeBlobView(new Blob([buffer]), size);
|
||||
});
|
||||
}
|
||||
|
||||
function readBlob(blob) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var reader = new FileReader();
|
||||
reader.readAsArrayBuffer(blob);
|
||||
reader.onload = function(event) {
|
||||
resolve(reader.result);
|
||||
};
|
||||
reader.onerror = function(event) {
|
||||
reject(event.target.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function readPicSlice(blob, picture) {
|
||||
var slice = blob.slice(picture.start, picture.end, picture.type);
|
||||
return readBlob(slice);
|
||||
}
|
||||
|
||||
function assertBuffersEqual(a, b) {
|
||||
return assert.deepEqual(new Uint8Array(a), new Uint8Array(b));
|
||||
}
|
||||
Loading…
Reference in a new issue