OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 '''Unit tests for ChromeScaledImage.''' | |
7 | |
8 | |
9 import re | |
10 import struct | |
11 import unittest | |
12 import zlib | |
13 | |
14 from grit import exception | |
15 from grit import util | |
16 from grit.format import data_pack | |
17 from grit.tool import build | |
18 | |
19 | |
20 _OUTFILETYPES = [ | |
21 ('.h', 'rc_header'), | |
22 ('_map.cc', 'resource_map_source'), | |
23 ('_map.h', 'resource_map_header'), | |
24 ('.pak', 'data_package'), | |
25 ('.rc', 'rc_all'), | |
26 ] | |
27 | |
28 | |
29 _PNG_HEADER = ( | |
30 '\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52' | |
31 '\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53' | |
32 '\xde') | |
33 _PNG_FOOTER = ( | |
34 '\x00\x00\x00\x0c\x49\x44\x41\x54\x18\x57\x63\xf8\xff\xff\x3f\x00' | |
35 '\x05\xfe\x02\xfe\xa7\x35\x81\x84\x00\x00\x00\x00\x49\x45\x4e\x44' | |
36 '\xae\x42\x60\x82') | |
37 | |
38 | |
39 def _MakePNG(chunks): | |
40 pack_int32 = struct.Struct('>i').pack | |
41 chunks = [pack_int32(len(payload)) + type + payload + pack_int32(zlib.crc32(ty
pe + payload)) | |
42 for type, payload in chunks] | |
43 return _PNG_HEADER + ''.join(chunks) + _PNG_FOOTER | |
44 | |
45 | |
46 def _GetFilesInPak(pakname): | |
47 '''Get a set of the files that were actually included in the .pak output. | |
48 ''' | |
49 return set(data_pack.DataPack.ReadDataPack(pakname).resources.values()) | |
50 | |
51 | |
52 def _GetFilesInRc(rcname, tmp_dir, contents): | |
53 '''Get a set of the files that were actually included in the .rc output. | |
54 ''' | |
55 data = util.ReadFile(rcname, util.BINARY).decode('utf-16') | |
56 contents = dict((tmp_dir.GetPath(k), v) for k, v in contents.items()) | |
57 return set(contents[m.group(1)] | |
58 for m in re.finditer(ur'(?m)^\w+\s+BINDATA\s+"([^"]+)"$', data)) | |
59 | |
60 | |
61 def _MakeFallbackAttr(fallback): | |
62 if fallback is None: | |
63 return '' | |
64 else: | |
65 return ' fallback_to_low_resolution="%s"' % ('false', 'true')[fallback] | |
66 | |
67 | |
68 def _Structures(fallback, *body): | |
69 return '<structures%s>\n%s\n</structures>' % ( | |
70 _MakeFallbackAttr(fallback), '\n'.join(body)) | |
71 | |
72 | |
73 def _Structure(name, file, fallback=None): | |
74 return '<structure name="%s" file="%s" type="chrome_scaled_image"%s />' % ( | |
75 name, file, _MakeFallbackAttr(fallback)) | |
76 | |
77 | |
78 def _If(expr, *body): | |
79 return '<if expr="%s">\n%s\n</if>' % (expr, '\n'.join(body)) | |
80 | |
81 | |
82 def _RunBuildTest(self, structures, inputs, expected_outputs, skip_rc=False, lay
out_fallback=''): | |
83 outputs = '\n'.join('<output filename="out/%s%s" type="%s" context="%s"%s />' | |
84 % (context, ext, type, context, layout_fallback) | |
85 for ext, type in _OUTFILETYPES | |
86 for context in expected_outputs) | |
87 | |
88 infiles = { | |
89 'in/in.grd': '''<?xml version="1.0" encoding="UTF-8"?> | |
90 <grit latest_public_release="0" current_release="1"> | |
91 <outputs> | |
92 %s | |
93 </outputs> | |
94 <release seq="1"> | |
95 %s | |
96 </release> | |
97 </grit> | |
98 ''' % (outputs, structures), | |
99 } | |
100 for pngpath, pngdata in inputs.items(): | |
101 infiles['in/' + pngpath] = pngdata | |
102 class Options(object): | |
103 pass | |
104 with util.TempDir(infiles) as tmp_dir: | |
105 with tmp_dir.AsCurrentDir(): | |
106 options = Options() | |
107 options.input = tmp_dir.GetPath('in/in.grd') | |
108 options.verbose = False | |
109 options.extra_verbose = False | |
110 build.RcBuilder().Run(options, []) | |
111 for context, expected_data in expected_outputs.items(): | |
112 self.assertEquals(expected_data, | |
113 _GetFilesInPak(tmp_dir.GetPath('out/%s.pak' % context))) | |
114 if not skip_rc: | |
115 self.assertEquals(expected_data, | |
116 _GetFilesInRc(tmp_dir.GetPath('out/%s.rc' % context), | |
117 tmp_dir, infiles)) | |
118 | |
119 | |
120 class ChromeScaledImageUnittest(unittest.TestCase): | |
121 def testNormalFallback(self): | |
122 d123a = _MakePNG([('AbCd', '')]) | |
123 t123a = _MakePNG([('EfGh', '')]) | |
124 d123b = _MakePNG([('IjKl', '')]) | |
125 _RunBuildTest(self, | |
126 _Structures(None, | |
127 _Structure('IDR_A', 'a.png'), | |
128 _Structure('IDR_B', 'b.png'), | |
129 ), | |
130 {'default_123_percent/a.png': d123a, | |
131 'tactile_123_percent/a.png': t123a, | |
132 'default_123_percent/b.png': d123b, | |
133 }, | |
134 {'default_123_percent': set([d123a, d123b]), | |
135 'tactile_123_percent': set([t123a, d123b]), | |
136 }) | |
137 | |
138 def testNormalFallbackFailure(self): | |
139 self.assertRaises(exception.FileNotFound, | |
140 _RunBuildTest, self, | |
141 _Structures(None, | |
142 _Structure('IDR_A', 'a.png'), | |
143 ), | |
144 {'default_100_percent/a.png': _MakePNG([('AbCd', '')]), | |
145 'tactile_100_percent/a.png': _MakePNG([('EfGh', '')]), | |
146 }, | |
147 {'tactile_123_percent': 'should fail before using this'}) | |
148 | |
149 def testLowresFallback(self): | |
150 png = _MakePNG([('Abcd', '')]) | |
151 png_with_csCl = _MakePNG([('csCl', ''),('Abcd', '')]) | |
152 for outer in (None, False, True): | |
153 for inner in (None, False, True): | |
154 args = ( | |
155 self, | |
156 _Structures(outer, | |
157 _Structure('IDR_A', 'a.png', inner), | |
158 ), | |
159 {'default_100_percent/a.png': png}, | |
160 {'tactile_200_percent': set([png_with_csCl])}) | |
161 if inner or (inner is None and outer): | |
162 # should fall back to 100% | |
163 _RunBuildTest(*args, skip_rc=True) | |
164 else: | |
165 # shouldn't fall back | |
166 self.assertRaises(exception.FileNotFound, _RunBuildTest, *args) | |
167 | |
168 # Test fallback failure with fallback_to_low_resolution=True | |
169 self.assertRaises(exception.FileNotFound, | |
170 _RunBuildTest, self, | |
171 _Structures(True, | |
172 _Structure('IDR_A', 'a.png'), | |
173 ), | |
174 {}, # no files | |
175 {'tactile_123_percent': 'should fail before using this'}) | |
176 | |
177 def testNoFallbackToDefaultLayout(self): | |
178 d123a = _MakePNG([('AbCd', '')]) | |
179 t123a = _MakePNG([('EfGh', '')]) | |
180 d123b = _MakePNG([('IjKl', '')]) | |
181 _RunBuildTest(self, | |
182 _Structures(None, | |
183 _Structure('IDR_A', 'a.png'), | |
184 _Structure('IDR_B', 'b.png'), | |
185 ), | |
186 {'default_123_percent/a.png': d123a, | |
187 'tactile_123_percent/a.png': t123a, | |
188 'default_123_percent/b.png': d123b, | |
189 }, | |
190 {'default_123_percent': set([d123a, d123b]), | |
191 'tactile_123_percent': set([t123a]), | |
192 }, | |
193 layout_fallback=' fallback_to_default_layout="false"') | |
OLD | NEW |