1#!/usr/bin/python
2
3import re
4import unittest
5
6import napi.fs
7import napi.sandbox
8import napi.subtitles
9import napi.testcase
10
11class LegacyApiModeTest(napi.testcase.NapiTestCase):
12
13    def test_ifFailsCorrectlyIfSubsUnavailable(self):
14        """
15        Brief:
16        Verify if handles subs acquisition failure without any errors
17
18        Procedure:
19        1. Prepare media file
20        2. Program napi mock to respond with no data and 404 HTTP Status
21        3. Call napi.sh in legacy mode with id = pynapi
22
23        Expected Results:
24        No processing errors should be detected. Normal error response handling
25        should be done. No files should be produced afterwards.
26
27        """
28        media = None
29        with napi.sandbox.Sandbox() as sandbox:
30            # generate a media file
31            media = self.videoAssets.prepareRandomMedia(sandbox)
32
33            # program napiprojekt mock
34            self.napiMock.programPlainRequest()
35
36            # call napi
37            self.isStderrExpected = True
38            self.napiScan('-i', 'pynapi', media['path'])
39            fs = napi.fs.Filesystem(media)
40
41            # check assertions
42            req = self.napiMock.getRequest()
43            self.assertEquals(req.method, "GET")
44            self.assertTrue(re.match(r'/unit_napisy/dl\.php\?', req.url))
45
46            self.assertTrue(self.output.hasErrors())
47            self.assertTrue(self.output.stderrContains(
48                re.compile(r'nie udalo sie pobrac napisow')))
49            self.assertFalse(fs.subtitlesExists())
50
51
52    def test_ifFailsCorrectlyIfResponseIsTooShort(self):
53        """
54        Brief: Verify if napi fails responses which are awkwardly short.
55        Procedure:
56        1. Prepare a media file
57        2. Program napi mock to respond with:
58        4
59        NPc0
60        0
61
62        This response most of the time indicates lack of requested subtitles.
63
64        Expected Results:
65        No processing errors should be detected. Normal error response handling
66        should be done. No files should be produced afterwards.
67        """
68        media = None
69        with napi.sandbox.Sandbox() as sandbox:
70            # generate a media file
71            media = self.videoAssets.prepareRandomMedia(sandbox)
72
73            # program napiprojekt mock
74            self.napiMock.programPlainRequest(
75                    napi.subtitles.Subtitles.fromString(
76                        media['asset'], '4\nNPc0\n0'))
77
78            # call napi
79            self.isStderrExpected = True
80            self.napiScan('-i', 'pynapi', media['path'])
81            fs = napi.fs.Filesystem(media)
82
83            # check assertions
84            req = self.napiMock.getRequest()
85            self.assertEquals(req.method, "GET")
86            self.assertTrue(re.match(r'/unit_napisy/dl\.php\?', req.url))
87
88            self.assertTrue(self.output.hasErrors())
89            self.assertTrue(self.output.stdoutContains(
90                re.compile(r'plik uszkodzony. niepoprawna ilosc linii')))
91            self.assertFalse(fs.subtitlesExists())
92
93
94    def test_ifFetchesSingleCompressedFile(self):
95        """
96        Brief:
97        Verify if napi works for single media files in legacy mode (other)
98
99        Procedure:
100        1. Prepare subtitles media
101        2. Prepare video media
102        3. Program napi mock to respond with plain compressed subs HTTP
103        response for GET request
104        4. Call napi.sh in legacy mode with id = other
105
106        Expected Results:
107        napi.sh should perform a GET request to napi.sh using legacy API.
108        Subtitles file should exist afterwards.
109        """
110        media = None
111        subsMedia = None
112        with napi.sandbox.Sandbox() as sandbox:
113            # generate a media file
114            media = self.videoAssets.prepareRandomMedia(sandbox)
115            subsMedia = self.subtitlesAssets.prepareRandomMedia(sandbox)
116
117            # program napiprojekt mock
118            self.napiMock.programPlainRequest(
119                    napi.subtitles.CompressedSubtitles.fromFile(
120                        media['asset'], subsMedia['path']))
121
122            # call napi
123            self.napiScan('-i', 'other', media['path'])
124            fs = napi.fs.Filesystem(media)
125
126            # check assertions
127            req = self.napiMock.getRequest()
128            self.assertEquals(req.method, "GET")
129            self.assertTrue(re.match(r'/unit_napisy/dl\.php\?', req.url))
130
131            self.assertTrue(self.output.stdoutContains(
132                re.compile(r'napisy pobrano pomyslnie')))
133
134            self.assertTrue(fs.subtitlesExists())
135
136    def test_ifFetchesSingleMediaFile(self):
137        """
138        Brief:
139        Verify if napi works for single media files in legacy mode (pynapi)
140
141        Procedure:
142        1. Prepare subtitles media
143        2. Prepare video media
144        3. Program napi mock to respond with plain subs HTTP response for GET
145        request
146        4. Call napi.sh in legacy mode with id = pynapi
147
148        Expected Results:
149        napi.sh should perform a GET request to napi.sh using legacy API.
150        Subtitles file should exist afterwards.
151        """
152        media = None
153        subsMedia = None
154        with napi.sandbox.Sandbox() as sandbox:
155            # generate a media file
156            media = self.videoAssets.prepareRandomMedia(sandbox)
157            subsMedia = self.subtitlesAssets.prepareRandomMedia(sandbox)
158
159            # program napiprojekt mock
160            self.napiMock.programPlainRequest(
161                    napi.subtitles.Subtitles.fromFile(
162                        media['asset'], subsMedia['path']))
163
164            # call napi
165            self.napiScan('-i', 'pynapi', media['path'])
166            fs = napi.fs.Filesystem(media)
167
168            # check assertions
169            req = self.napiMock.getRequest()
170            self.assertEquals(req.method, "GET")
171            self.assertTrue(re.match(r'/unit_napisy/dl\.php\?', req.url))
172
173            self.assertTrue(self.output.stdoutContains(
174                re.compile(r'napisy pobrano pomyslnie')))
175
176            self.assertTrue(fs.subtitlesExists())
177
178    def test_ifScanWorksForDirectory(self):
179        """
180        Brief: Verify if napi works for specified media directory
181        Procedure:
182        1. Prepare sandbox and media files with random names
183        2. Program napiprojekt mock to reply with success for some of the media
184        files and failure for the others.
185        3. Call napi with the path to the sandbox
186
187        Expected Results:
188        Napi should successfully download subtitles for media files for which
189        napiprojekt mock has been programmed to return a successful result.
190        """
191        mediasAvailable = []
192        mediasUnavailable = []
193        with napi.sandbox.Sandbox() as sandbox:
194
195            nAvailable = 3
196            nUnavailable = 3
197            nTotal = nAvailable + nUnavailable
198
199            # prepare responses for available subs
200            for _ in xrange(nAvailable):
201                media = self.videoAssets.prepareRandomMedia(sandbox)
202                subsMedia = self.subtitlesAssets.prepareRandomMedia(sandbox)
203                mediasAvailable.append(media)
204
205                # program http mock
206                self.napiMock.programPlainRequest(
207                        napi.subtitles.Subtitles.fromFile(
208                            media['asset'], subsMedia['path']))
209
210            # prepare responses for unavailable subs
211            for _ in xrange(nUnavailable):
212                media = self.videoAssets.prepareRandomMedia(sandbox)
213                mediasUnavailable.append(media)
214                self.napiMock.programPlainRequest()
215
216            # call napi
217            self.isStderrExpected = True
218            self.napiScan('--stats', '-i', 'pynapi', sandbox.path)
219
220            # check assertions
221            for n in xrange(nTotal):
222                req = self.napiMock.getRequest(n)
223                self.assertEquals(req.method, "GET")
224                self.assertTrue(re.match(r'/unit_napisy/dl\.php\?', req.url))
225
226            # check statistics
227            stats = self.output.parseNapiStats()
228            self.assertEquals(nAvailable, stats['ok'])
229            self.assertEquals(nUnavailable, stats['unav'])
230            self.assertEquals(nTotal, stats['total'])
231
232            allMedia = mediasAvailable + mediasUnavailable
233            self.assertEqual(nAvailable, sum([ 1 for m in allMedia
234                if napi.fs.Filesystem(m).subtitlesExists()]))
235
236    def test_ifSkippingWorks(self):
237        """
238        Brief:
239        This test verifies if napi is skipping the subtitles download for media
240        files for which the subtitles file seems to already exist in the
241        filesystem.
242
243        Procedure:
244        1. Prepare a set of media files.
245        2. Program napiprojekt.pl mock to respond with success response.
246        3. Call napi -s.
247        4. Call napi -s again.
248
249        Expected Results:
250        Check if it skipped the download for media files for which subtitles
251        have been already obtained.
252
253        """
254        medias = []
255        with napi.sandbox.Sandbox() as sandbox:
256
257            nTotal = 4
258            nAttempts = 3
259
260            # prepare responses for available subs
261            for _ in xrange(nTotal):
262                media = self.videoAssets.prepareRandomMedia(sandbox)
263                subsMedia = self.subtitlesAssets.prepareRandomMedia(sandbox)
264                medias.append(media)
265
266                # program http mock
267                self.napiMock.programPlainRequest(
268                        napi.subtitles.CompressedSubtitles.fromFile(
269                            media['asset'], subsMedia['path']),
270                        200,
271                        nAttempts)
272
273            for attempt in xrange(nAttempts):
274                # call napi
275                self.napiScan('--stats', '-s', '-i', 'pynapi', sandbox.path)
276
277                stats = self.output.parseNapiStats()
278                if attempt == 0:
279                    for n in xrange(nTotal):
280                        req = self.napiMock.getRequest(n + nTotal*attempt)
281                        self.assertTrue(req)
282                        self.assertEquals(req.method, "GET")
283                        self.assertTrue(re.match(r'/unit_napisy/dl\.php\?', req.url))
284
285                    # check statistics
286                    self.assertEquals(nTotal, stats['ok'])
287                    self.assertEquals(0, stats['skip'])
288                    self.assertEquals(0, stats['unav'])
289                    self.assertEquals(nTotal, stats['total'])
290                else:
291                    for n in xrange(nTotal):
292                        req = self.napiMock.getRequest(n + nTotal*attempt)
293                        self.assertFalse(req)
294
295                    # check statistics
296                    self.assertEquals(0, stats['ok'])
297                    self.assertEquals(nTotal, stats['skip'])
298                    self.assertEquals(0, stats['unav'])
299                    self.assertEquals(nTotal, stats['total'])
300
301                self.assertEqual(nTotal, sum([ 1 for m in medias
302                    if napi.fs.Filesystem(m).subtitlesExists()]))
303
304# # Brief:
305# #
306# # Verify if napi works for specified media directory and skips downloading if the subtitles file already exist
307# #
308# # Preconditions:
309# # - prepare a set of test files and a test directory structure
310# # - the subtitles files should exist as well
311# #
312# # Procedure:
313# # - Call napi with the path to the pre-prepared media directory
314# #
315# # Expected results:
316# # - napi shouldn't download the subtitles for the media files (for which they are available) if it detects that the
317# # subtitles file already exist
318# #
319# $output = NapiTest::qx_napi($shell, " --id pynapi --stats -s " . $NapiTest::testspace);
320# %output = NapiTest::parse_summary($output);
321# is ($output{skip}, $total_available, "Total number of skipped");
322# is ($output{skip} + $output{unav}, $output{total}, "Total processed (with skipping)");
323# is ($output{total}, $total_available + $total_unavailable, "Total processed (with skipping) 2");
324
325if __name__ == '__main__':
326    napi.testcase.runTests()
327