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 grit.tool.android2grd'''
7
8import os
9import sys
10if __name__ == '__main__':
11  sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
12
13import unittest
14import xml.dom.minidom
15
16from grit import grd_reader
17from grit import util
18from grit.node import empty
19from grit.node import io
20from grit.node import message
21from grit.node import misc
22from grit.tool import android2grd
23
24
25class Android2GrdUnittest(unittest.TestCase):
26
27  def __Parse(self, xml_string):
28    return xml.dom.minidom.parseString(xml_string).childNodes[0]
29
30  def testCreateTclibMessage(self):
31    tool = android2grd.Android2Grd()
32    msg = tool.CreateTclibMessage(self.__Parse(r'''
33        <string name="simple">A simple string</string>'''))
34    self.assertEqual(msg.GetRealContent(), 'A simple string')
35    msg = tool.CreateTclibMessage(self.__Parse(r'''
36        <string name="outer_whitespace">
37          Strip leading/trailing whitespace
38        </string>'''))
39    self.assertEqual(msg.GetRealContent(), 'Strip leading/trailing whitespace')
40    msg = tool.CreateTclibMessage(self.__Parse(r'''
41        <string name="inner_whitespace">Fold  multiple   spaces</string>'''))
42    self.assertEqual(msg.GetRealContent(), 'Fold multiple spaces')
43    msg = tool.CreateTclibMessage(self.__Parse(r'''
44        <string name="escaped_spaces">Retain \n escaped\t spaces</string>'''))
45    self.assertEqual(msg.GetRealContent(), 'Retain \n escaped\t spaces')
46    msg = tool.CreateTclibMessage(self.__Parse(r'''
47        <string name="quotes">   " Quotes  preserve
48          whitespace"  but  only  for  "enclosed   elements  "
49        </string>'''))
50    self.assertEqual(msg.GetRealContent(), ''' Quotes  preserve
51          whitespace but only for enclosed   elements  ''')
52    msg = tool.CreateTclibMessage(self.__Parse(
53        r'''<string name="escaped_characters">Escaped characters: \"\'\\\t\n'''
54        '</string>'))
55    self.assertEqual(msg.GetRealContent(), '''Escaped characters: "'\\\t\n''')
56    msg = tool.CreateTclibMessage(self.__Parse(
57        '<string xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" '
58        'name="placeholders">'
59        'Open <xliff:g id="FILENAME" example="internet.html">%s</xliff:g>?'
60        '</string>'))
61    self.assertEqual(msg.GetRealContent(), 'Open %s?')
62    self.assertEqual(len(msg.GetPlaceholders()), 1)
63    self.assertEqual(msg.GetPlaceholders()[0].presentation, 'FILENAME')
64    self.assertEqual(msg.GetPlaceholders()[0].original, '%s')
65    self.assertEqual(msg.GetPlaceholders()[0].example, 'internet.html')
66    msg = tool.CreateTclibMessage(self.__Parse(r'''
67        <string name="comment">Contains a <!-- ignore this --> comment
68        </string>'''))
69    self.assertEqual(msg.GetRealContent(), 'Contains a comment')
70
71  def testIsTranslatable(self):
72    tool = android2grd.Android2Grd()
73    string_el = self.__Parse('<string>Hi</string>')
74    self.assertTrue(tool.IsTranslatable(string_el))
75    string_el = self.__Parse(
76        '<string translatable="true">Hi</string>')
77    self.assertTrue(tool.IsTranslatable(string_el))
78    string_el = self.__Parse(
79        '<string translatable="false">Hi</string>')
80    self.assertFalse(tool.IsTranslatable(string_el))
81
82  def __ParseAndroidXml(self, options = []):
83    tool = android2grd.Android2Grd()
84
85    tool.ParseOptions(options)
86
87    android_path = util.PathFromRoot('grit/testdata/android.xml')
88    with open(android_path) as android_file:
89      android_dom = xml.dom.minidom.parse(android_file)
90
91    grd = tool.AndroidDomToGrdDom(android_dom)
92    self.assertTrue(isinstance(grd, misc.GritNode))
93
94    return grd
95
96  def testAndroidDomToGrdDom(self):
97    grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru'])
98
99    # Check that the structure of the GritNode is as expected.
100    messages = grd.GetChildrenOfType(message.MessageNode)
101    translations = grd.GetChildrenOfType(empty.TranslationsNode)
102    files = grd.GetChildrenOfType(io.FileNode)
103
104    self.assertEqual(len(translations), 1)
105    self.assertEqual(len(files), 3)
106    self.assertEqual(len(messages), 5)
107
108    # Check that a message node is constructed correctly.
109    msg = filter(lambda x: x.GetTextualIds()[0] == "IDS_PLACEHOLDERS", messages)
110    self.assertTrue(msg)
111    msg = msg[0]
112
113    self.assertTrue(msg.IsTranslateable())
114    self.assertEqual(msg.attrs["desc"], "A string with placeholder.")
115
116  def testProductAttribute(self):
117    grd = self.__ParseAndroidXml([])
118    messages = grd.GetChildrenOfType(message.MessageNode)
119    msg = filter(lambda x: x.GetTextualIds()[0] ==
120                   "IDS_SIMPLE_product_nosdcard",
121                 messages)
122    self.assertTrue(msg)
123
124  def testTranslatableAttribute(self):
125    grd = self.__ParseAndroidXml([])
126    messages = grd.GetChildrenOfType(message.MessageNode)
127    msgs = filter(lambda x: x.GetTextualIds()[0] == "IDS_CONSTANT", messages)
128    self.assertTrue(msgs)
129    self.assertFalse(msgs[0].IsTranslateable())
130
131  def testTranslations(self):
132    grd = self.__ParseAndroidXml(['--languages', 'en-US,en-GB,ru,id'])
133
134    files = grd.GetChildrenOfType(io.FileNode)
135    us_file = filter(lambda x: x.attrs['lang'] == 'en-US', files)
136    self.assertTrue(us_file)
137    self.assertEqual(us_file[0].GetInputPath(),
138                     'chrome_android_strings_en-US.xtb')
139
140    id_file = filter(lambda x: x.attrs['lang'] == 'id', files)
141    self.assertTrue(id_file)
142    self.assertEqual(id_file[0].GetInputPath(),
143                     'chrome_android_strings_id.xtb')
144
145  def testOutputs(self):
146    grd = self.__ParseAndroidXml(['--languages', 'en-US,ru,id',
147                                  '--rc-dir', 'rc/dir',
148                                  '--header-dir', 'header/dir',
149                                  '--xtb-dir', 'xtb/dir',
150                                  '--xml-dir', 'xml/dir'])
151
152    outputs = grd.GetChildrenOfType(io.OutputNode)
153    self.assertEqual(len(outputs), 7)
154
155    header_outputs = filter(lambda x: x.GetType() == 'rc_header', outputs)
156    rc_outputs = filter(lambda x: x.GetType() == 'rc_all', outputs)
157    xml_outputs = filter(lambda x: x.GetType() == 'android', outputs)
158
159    self.assertEqual(len(header_outputs), 1)
160    self.assertEqual(len(rc_outputs), 3)
161    self.assertEqual(len(xml_outputs), 3)
162
163    # The header node should have an "<emit>" child and the proper filename.
164    self.assertTrue(header_outputs[0].GetChildrenOfType(io.EmitNode))
165    self.assertEqual(util.normpath(header_outputs[0].GetFilename()),
166                     util.normpath('header/dir/chrome_android_strings.h'))
167
168    id_rc = filter(lambda x: x.GetLanguage() == 'id', rc_outputs)
169    id_xml = filter(lambda x: x.GetLanguage() == 'id', xml_outputs)
170    self.assertTrue(id_rc)
171    self.assertTrue(id_xml)
172    self.assertEqual(util.normpath(id_rc[0].GetFilename()),
173                     util.normpath('rc/dir/chrome_android_strings_id.rc'))
174    self.assertEqual(util.normpath(id_xml[0].GetFilename()),
175                     util.normpath('xml/dir/values-in/strings.xml'))
176
177    us_rc = filter(lambda x: x.GetLanguage() == 'en-US', rc_outputs)
178    us_xml = filter(lambda x: x.GetLanguage() == 'en-US', xml_outputs)
179    self.assertTrue(us_rc)
180    self.assertTrue(us_xml)
181    self.assertEqual(util.normpath(us_rc[0].GetFilename()),
182                     util.normpath('rc/dir/chrome_android_strings_en-US.rc'))
183    self.assertEqual(util.normpath(us_xml[0].GetFilename()),
184                     util.normpath('xml/dir/values-en-rUS/strings.xml'))
185
186
187if __name__ == '__main__':
188  unittest.main()
189