1# -*- coding: utf-8 -*-
2# Copyright 2014 Ben Ockmore
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8
9"""Tests for mid3cp tool. Since the tool is quite simple, most of the
10functionality is covered by the mutagen package tests - these simply test
11usage.
12"""
13
14import os
15from tempfile import mkstemp
16import shutil
17
18import mutagen.id3
19from mutagen.id3 import ID3, ParseID3v1
20from mutagen._senf import fsnative as fsn
21
22from tests.test_tools import _TTools
23from tests import DATA_DIR
24
25
26class TMid3cp(_TTools):
27
28    TOOL_NAME = u"mid3cp"
29
30    def setUp(self):
31        super(TMid3cp, self).setUp()
32        original = os.path.join(DATA_DIR, fsn(u'silence-44-s.mp3'))
33        fd, self.filename = mkstemp(suffix=fsn(u'öäü.mp3'))
34        os.close(fd)
35        shutil.copy(original, self.filename)
36
37        fd, self.blank_file = mkstemp(suffix=fsn(u'.mp3'))
38        os.close(fd)
39
40    def tearDown(self):
41        super(TMid3cp, self).tearDown()
42        os.unlink(self.filename)
43        os.unlink(self.blank_file)
44
45    def test_merge(self):
46        id3 = ID3(self.filename)
47        id3.delete()
48        id3.add(mutagen.id3.TALB(text=[u"foo"]))
49        id3.save(v2_version=3)
50
51        target = ID3()
52        target.add(mutagen.id3.TPE1(text=[u"bar", u"quux"]))
53        target.save(self.blank_file, v2_version=4)
54
55        res, out, err = self.call2(
56            self.filename, self.blank_file, fsn(u"--merge"))
57        assert not any([res, out, err])
58
59        result = ID3(self.blank_file)
60        assert result.version == (2, 4, 0)
61        assert result.getall("TALB")[0].text == [u"foo"]
62        assert result.getall("TPE1")[0].text == [u"bar", u"quux"]
63
64    def test_merge_dst_no_tag(self):
65        id3 = ID3(self.filename)
66        id3.delete()
67        id3.save(v2_version=3)
68
69        with open(self.blank_file, "wb") as h:
70            h.write(b"SOMEDATA")
71        res, out, err = self.call2(
72            self.filename, self.blank_file, fsn(u"--merge"))
73        assert not any([res, out, err])
74
75        result = ID3(self.blank_file)
76        assert result.version == (2, 3, 0)
77
78    def test_noop(self):
79        res, out, err = self.call2()
80        self.assertNotEqual(res, 0)
81        self.failUnless("Usage:" in err)
82
83    def test_src_equal_dst(self):
84        res = self.call2(self.filename, self.filename)[0]
85        self.assertEqual(res, 0)
86
87    def test_copy(self):
88        res = self.call(self.filename, self.blank_file)[0]
89        self.failIf(res)
90
91        original_id3 = ID3(self.filename)
92        copied_id3 = ID3(self.blank_file)
93        self.assertEqual(copied_id3.version, (2, 3, 0))
94
95        # XXX: the v2.3 frame contains duplicate TPE1 frames which get merged
96        # when saving to v2.3 again
97        frame = copied_id3["TPE1"]
98        frame.text = frame.text[0].split("/")
99
100        self.failUnlessEqual(original_id3, copied_id3)
101
102        for key in original_id3:
103            # Go through every tag in the original file, and check that it's
104            # present and correct in the copy
105            self.failUnless(key in copied_id3)
106            self.failUnlessEqual(copied_id3[key], original_id3[key])
107
108    def test_include_id3v1(self):
109        self.call(fsn(u'--write-v1'), self.filename, self.blank_file)
110
111        with open(self.blank_file, 'rb') as fileobj:
112            fileobj.seek(-128, 2)
113            frames = ParseID3v1(fileobj.read(128))
114
115        # If ID3v1 frames are present, assume they've been written correctly by
116        # mutagen, so no need to check them
117        self.failUnless(frames)
118
119    def test_exclude_tag_unicode(self):
120        self.call(fsn(u'-x'), fsn(u''), self.filename, self.blank_file)
121
122    def test_exclude_single_tag(self):
123        self.call(fsn(u'-x'), fsn(u'TLEN'), self.filename, self.blank_file)
124
125        original_id3 = ID3(self.filename)
126        copied_id3 = ID3(self.blank_file)
127
128        self.failUnless('TLEN' in original_id3)
129        self.failIf('TLEN' in copied_id3)
130
131    def test_exclude_multiple_tag(self):
132        self.call(fsn(u'-x'), fsn(u'TLEN'), fsn(u'-x'), fsn(u'TCON'),
133                  fsn(u'-x'), fsn(u'TALB'), self.filename, self.blank_file)
134
135        original_id3 = ID3(self.filename)
136        copied_id3 = ID3(self.blank_file)
137
138        self.failUnless('TLEN' in original_id3)
139        self.failUnless('TCON' in original_id3)
140        self.failUnless('TALB' in original_id3)
141        self.failIf('TLEN' in copied_id3)
142        self.failIf('TCON' in copied_id3)
143        self.failIf('TALB' in copied_id3)
144
145    def test_no_src_header(self):
146        fd, blank_file2 = mkstemp(suffix=fsn(u'.mp3'))
147        os.close(fd)
148        try:
149            err = self.call2(self.blank_file, blank_file2)[2]
150            self.failUnless("No ID3 header found" in err)
151        finally:
152            os.unlink(blank_file2)
153
154    def test_verbose(self):
155        err = self.call2(self.filename, fsn(u"--verbose"), self.blank_file)[2]
156        self.failUnless('mp3 contains:' in err)
157        self.failUnless('Successfully saved' in err)
158
159    def test_quiet(self):
160        out = self.call(self.filename, self.blank_file)[1]
161        self.failIf(out)
162
163    def test_exit_status(self):
164        status, out, err = self.call2(self.filename)
165        self.assertTrue(status)
166
167        status, out, err = self.call2(self.filename, self.filename)
168        self.assertFalse(status)
169
170        status, out, err = self.call2(self.blank_file, self.filename)
171        self.assertTrue(status)
172
173        status, out, err = self.call2(fsn(u""), self.filename)
174        self.assertTrue(status)
175
176        status, out, err = self.call2(self.filename, self.blank_file)
177        self.assertFalse(status)
178
179    def test_v23_v24(self):
180        self.assertEqual(ID3(self.filename).version, (2, 3, 0))
181        self.call(self.filename, self.blank_file)
182        self.assertEqual(ID3(self.blank_file).version, (2, 3, 0))
183
184        ID3(self.filename).save()
185        self.call(self.filename, self.blank_file)
186        self.assertEqual(ID3(self.blank_file).version, (2, 4, 0))
187