1 /***************************************************************************
2     copyright           : (C) 2007 by Lukas Lalinsky
3     email               : lukas@oxygene.sk
4  ***************************************************************************/
5 
6 /***************************************************************************
7  *   This library is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU Lesser General Public License version   *
9  *   2.1 as published by the Free Software Foundation.                     *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful, but   *
12  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the Free Software   *
18  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA         *
19  *   02110-1301  USA                                                       *
20  *                                                                         *
21  *   Alternatively, this file is available under the Mozilla Public        *
22  *   License Version 1.1.  You may obtain a copy of the License at         *
23  *   http://www.mozilla.org/MPL/                                           *
24  ***************************************************************************/
25 
26 #include <string>
27 #include <stdio.h>
28 #include <tag.h>
29 #include <fileref.h>
30 #include <oggflacfile.h>
31 #include <vorbisfile.h>
32 #include <mpegfile.h>
33 #include <mpcfile.h>
34 #include <asffile.h>
35 #include <speexfile.h>
36 #include <flacfile.h>
37 #include <trueaudiofile.h>
38 #include <mp4file.h>
39 #include <wavfile.h>
40 #include <apefile.h>
41 #include <aifffile.h>
42 #include <tfilestream.h>
43 #include <tbytevectorstream.h>
44 #include <cppunit/extensions/HelperMacros.h>
45 #include "utils.h"
46 
47 using namespace std;
48 using namespace TagLib;
49 
50 namespace
51 {
52   class DummyResolver : public FileRef::FileTypeResolver
53   {
54   public:
createFile(FileName fileName,bool,AudioProperties::ReadStyle) const55     virtual File *createFile(FileName fileName, bool, AudioProperties::ReadStyle) const
56     {
57       return new Ogg::Vorbis::File(fileName);
58     }
59   };
60 }
61 
62 class TestFileRef : public CppUnit::TestFixture
63 {
64   CPPUNIT_TEST_SUITE(TestFileRef);
65   CPPUNIT_TEST(testASF);
66   CPPUNIT_TEST(testMusepack);
67   CPPUNIT_TEST(testVorbis);
68   CPPUNIT_TEST(testSpeex);
69   CPPUNIT_TEST(testFLAC);
70   CPPUNIT_TEST(testMP3);
71   CPPUNIT_TEST(testOGA_FLAC);
72   CPPUNIT_TEST(testOGA_Vorbis);
73   CPPUNIT_TEST(testMP4_1);
74   CPPUNIT_TEST(testMP4_2);
75   CPPUNIT_TEST(testMP4_3);
76   CPPUNIT_TEST(testMP4_4);
77   CPPUNIT_TEST(testTrueAudio);
78   CPPUNIT_TEST(testAPE);
79   CPPUNIT_TEST(testWav);
80   CPPUNIT_TEST(testAIFF_1);
81   CPPUNIT_TEST(testAIFF_2);
82   CPPUNIT_TEST(testUnsupported);
83   CPPUNIT_TEST(testCreate);
84   CPPUNIT_TEST(testFileResolver);
85   CPPUNIT_TEST_SUITE_END();
86 
87 public:
88 
89   template <typename T>
fileRefSave(const string & filename,const string & ext)90   void fileRefSave(const string &filename, const string &ext)
91   {
92     ScopedFileCopy copy(filename, ext);
93     string newname = copy.fileName();
94 
95     {
96       FileRef f(newname.c_str());
97       CPPUNIT_ASSERT(dynamic_cast<T*>(f.file()));
98       CPPUNIT_ASSERT(!f.isNull());
99       f.tag()->setArtist("test artist");
100       f.tag()->setTitle("test title");
101       f.tag()->setGenre("Test!");
102       f.tag()->setAlbum("albummmm");
103       f.tag()->setTrack(5);
104       f.tag()->setYear(2020);
105       f.save();
106     }
107     {
108       FileRef f(newname.c_str());
109       CPPUNIT_ASSERT(!f.isNull());
110       CPPUNIT_ASSERT_EQUAL(f.tag()->artist(), String("test artist"));
111       CPPUNIT_ASSERT_EQUAL(f.tag()->title(), String("test title"));
112       CPPUNIT_ASSERT_EQUAL(f.tag()->genre(), String("Test!"));
113       CPPUNIT_ASSERT_EQUAL(f.tag()->album(), String("albummmm"));
114       CPPUNIT_ASSERT_EQUAL(f.tag()->track(), (unsigned int)5);
115       CPPUNIT_ASSERT_EQUAL(f.tag()->year(), (unsigned int)2020);
116       f.tag()->setArtist("ttest artist");
117       f.tag()->setTitle("ytest title");
118       f.tag()->setGenre("uTest!");
119       f.tag()->setAlbum("ialbummmm");
120       f.tag()->setTrack(7);
121       f.tag()->setYear(2080);
122       f.save();
123     }
124     {
125       FileRef f(newname.c_str());
126       CPPUNIT_ASSERT(!f.isNull());
127       CPPUNIT_ASSERT_EQUAL(f.tag()->artist(), String("ttest artist"));
128       CPPUNIT_ASSERT_EQUAL(f.tag()->title(), String("ytest title"));
129       CPPUNIT_ASSERT_EQUAL(f.tag()->genre(), String("uTest!"));
130       CPPUNIT_ASSERT_EQUAL(f.tag()->album(), String("ialbummmm"));
131       CPPUNIT_ASSERT_EQUAL(f.tag()->track(), (unsigned int)7);
132       CPPUNIT_ASSERT_EQUAL(f.tag()->year(), (unsigned int)2080);
133     }
134 
135     {
136       FileStream fs(newname.c_str());
137       FileRef f(&fs);
138       CPPUNIT_ASSERT(dynamic_cast<T*>(f.file()));
139       CPPUNIT_ASSERT(!f.isNull());
140       CPPUNIT_ASSERT_EQUAL(f.tag()->artist(), String("ttest artist"));
141       CPPUNIT_ASSERT_EQUAL(f.tag()->title(), String("ytest title"));
142       CPPUNIT_ASSERT_EQUAL(f.tag()->genre(), String("uTest!"));
143       CPPUNIT_ASSERT_EQUAL(f.tag()->album(), String("ialbummmm"));
144       CPPUNIT_ASSERT_EQUAL(f.tag()->track(), (unsigned int)7);
145       CPPUNIT_ASSERT_EQUAL(f.tag()->year(), (unsigned int)2080);
146       f.tag()->setArtist("test artist");
147       f.tag()->setTitle("test title");
148       f.tag()->setGenre("Test!");
149       f.tag()->setAlbum("albummmm");
150       f.tag()->setTrack(5);
151       f.tag()->setYear(2020);
152       f.save();
153     }
154 
155     ByteVector fileContent;
156     {
157       FileStream fs(newname.c_str());
158       FileRef f(&fs);
159       CPPUNIT_ASSERT(dynamic_cast<T*>(f.file()));
160       CPPUNIT_ASSERT(!f.isNull());
161       CPPUNIT_ASSERT_EQUAL(f.tag()->artist(), String("test artist"));
162       CPPUNIT_ASSERT_EQUAL(f.tag()->title(), String("test title"));
163       CPPUNIT_ASSERT_EQUAL(f.tag()->genre(), String("Test!"));
164       CPPUNIT_ASSERT_EQUAL(f.tag()->album(), String("albummmm"));
165       CPPUNIT_ASSERT_EQUAL(f.tag()->track(), (unsigned int)5);
166       CPPUNIT_ASSERT_EQUAL(f.tag()->year(), (unsigned int)2020);
167 
168       fs.seek(0);
169       fileContent = fs.readBlock(fs.length());
170     }
171 
172     {
173       ByteVectorStream bs(fileContent);
174       FileRef f(&bs);
175       CPPUNIT_ASSERT(dynamic_cast<T*>(f.file()));
176       CPPUNIT_ASSERT(!f.isNull());
177       CPPUNIT_ASSERT_EQUAL(f.tag()->artist(), String("test artist"));
178       CPPUNIT_ASSERT_EQUAL(f.tag()->title(), String("test title"));
179       CPPUNIT_ASSERT_EQUAL(f.tag()->genre(), String("Test!"));
180       CPPUNIT_ASSERT_EQUAL(f.tag()->album(), String("albummmm"));
181       CPPUNIT_ASSERT_EQUAL(f.tag()->track(), (unsigned int)5);
182       CPPUNIT_ASSERT_EQUAL(f.tag()->year(), (unsigned int)2020);
183       f.tag()->setArtist("ttest artist");
184       f.tag()->setTitle("ytest title");
185       f.tag()->setGenre("uTest!");
186       f.tag()->setAlbum("ialbummmm");
187       f.tag()->setTrack(7);
188       f.tag()->setYear(2080);
189       f.save();
190 
191       fileContent = *bs.data();
192     }
193     {
194       ByteVectorStream bs(fileContent);
195       FileRef f(&bs);
196       CPPUNIT_ASSERT(dynamic_cast<T*>(f.file()));
197       CPPUNIT_ASSERT(!f.isNull());
198       CPPUNIT_ASSERT_EQUAL(f.tag()->artist(), String("ttest artist"));
199       CPPUNIT_ASSERT_EQUAL(f.tag()->title(), String("ytest title"));
200       CPPUNIT_ASSERT_EQUAL(f.tag()->genre(), String("uTest!"));
201       CPPUNIT_ASSERT_EQUAL(f.tag()->album(), String("ialbummmm"));
202       CPPUNIT_ASSERT_EQUAL(f.tag()->track(), (unsigned int)7);
203       CPPUNIT_ASSERT_EQUAL(f.tag()->year(), (unsigned int)2080);
204     }
205   }
206 
testMusepack()207   void testMusepack()
208   {
209     fileRefSave<MPC::File>("click", ".mpc");
210   }
211 
testASF()212   void testASF()
213   {
214     fileRefSave<ASF::File>("silence-1", ".wma");
215   }
216 
testVorbis()217   void testVorbis()
218   {
219     fileRefSave<Ogg::Vorbis::File>("empty", ".ogg");
220   }
221 
testSpeex()222   void testSpeex()
223   {
224     fileRefSave<Ogg::Speex::File>("empty", ".spx");
225   }
226 
testFLAC()227   void testFLAC()
228   {
229     fileRefSave<FLAC::File>("no-tags", ".flac");
230   }
231 
testMP3()232   void testMP3()
233   {
234     fileRefSave<MPEG::File>("xing", ".mp3");
235   }
236 
testTrueAudio()237   void testTrueAudio()
238   {
239     fileRefSave<TrueAudio::File>("empty", ".tta");
240   }
241 
testMP4_1()242   void testMP4_1()
243   {
244     fileRefSave<MP4::File>("has-tags", ".m4a");
245   }
246 
testMP4_2()247   void testMP4_2()
248   {
249     fileRefSave<MP4::File>("no-tags", ".m4a");
250   }
251 
testMP4_3()252   void testMP4_3()
253   {
254     fileRefSave<MP4::File>("no-tags", ".3g2");
255   }
256 
testMP4_4()257   void testMP4_4()
258   {
259     fileRefSave<MP4::File>("blank_video", ".m4v");
260   }
261 
testWav()262   void testWav()
263   {
264     fileRefSave<RIFF::WAV::File>("empty", ".wav");
265   }
266 
testOGA_FLAC()267   void testOGA_FLAC()
268   {
269     fileRefSave<Ogg::FLAC::File>("empty_flac", ".oga");
270   }
271 
testOGA_Vorbis()272   void testOGA_Vorbis()
273   {
274     fileRefSave<Ogg::Vorbis::File>("empty_vorbis", ".oga");
275   }
276 
testAPE()277   void testAPE()
278   {
279     fileRefSave<APE::File>("mac-399", ".ape");
280   }
281 
testAIFF_1()282   void testAIFF_1()
283   {
284     fileRefSave<RIFF::AIFF::File>("empty", ".aiff");
285   }
286 
testAIFF_2()287   void testAIFF_2()
288   {
289     fileRefSave<RIFF::AIFF::File>("alaw", ".aifc");
290   }
291 
testUnsupported()292   void testUnsupported()
293   {
294     FileRef f1(TEST_FILE_PATH_C("no-extension"));
295     CPPUNIT_ASSERT(f1.isNull());
296 
297     FileRef f2(TEST_FILE_PATH_C("unsupported-extension.xx"));
298     CPPUNIT_ASSERT(f2.isNull());
299   }
300 
testCreate()301   void testCreate()
302   {
303     // This is deprecated. But worth it to test.
304 
305     File *f = FileRef::create(TEST_FILE_PATH_C("empty_vorbis.oga"));
306     CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File*>(f));
307     delete f;
308 
309     f = FileRef::create(TEST_FILE_PATH_C("xing.mp3"));
310     CPPUNIT_ASSERT(dynamic_cast<MPEG::File*>(f));
311     delete f;
312   }
313 
testFileResolver()314   void testFileResolver()
315   {
316     {
317       FileRef f(TEST_FILE_PATH_C("xing.mp3"));
318       CPPUNIT_ASSERT(dynamic_cast<MPEG::File *>(f.file()) != NULL);
319     }
320 
321     DummyResolver resolver;
322     FileRef::addFileTypeResolver(&resolver);
323 
324     {
325       FileRef f(TEST_FILE_PATH_C("xing.mp3"));
326       CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File *>(f.file()) != NULL);
327     }
328   }
329 
330 };
331 
332 CPPUNIT_TEST_SUITE_REGISTRATION(TestFileRef);
333