Add support for named versions in NDK map files.

Test: nose2
Test: make checkbuild
Bug: None
Change-Id: Ic32cfb3e0db767f695b617c787733a6ef75030aa
diff --git a/cc/test_gen_stub_libs.py b/cc/test_gen_stub_libs.py
index 8611ef3..4df6cf8 100755
--- a/cc/test_gen_stub_libs.py
+++ b/cc/test_gen_stub_libs.py
@@ -25,6 +25,15 @@
 # pylint: disable=missing-docstring
 
 
+class DecodeApiLevelTest(unittest.TestCase):
+    def test_decode_api_level(self):
+        self.assertEqual(9, gsl.decode_api_level('9', {}))
+        self.assertEqual(9000, gsl.decode_api_level('O', {'O': 9000}))
+
+        with self.assertRaises(KeyError):
+            gsl.decode_api_level('O', {})
+
+
 class TagsTest(unittest.TestCase):
     def test_get_tags_no_tags(self):
         self.assertEqual([], gsl.get_tags(''))
@@ -34,12 +43,59 @@
         self.assertEqual(['foo', 'bar'], gsl.get_tags('# foo bar'))
         self.assertEqual(['bar', 'baz'], gsl.get_tags('foo # bar baz'))
 
+    def test_split_tag(self):
+        self.assertTupleEqual(('foo', 'bar'), gsl.split_tag('foo=bar'))
+        self.assertTupleEqual(('foo', 'bar=baz'), gsl.split_tag('foo=bar=baz'))
+        with self.assertRaises(ValueError):
+            gsl.split_tag('foo')
+
     def test_get_tag_value(self):
         self.assertEqual('bar', gsl.get_tag_value('foo=bar'))
         self.assertEqual('bar=baz', gsl.get_tag_value('foo=bar=baz'))
         with self.assertRaises(ValueError):
             gsl.get_tag_value('foo')
 
+    def test_is_api_level_tag(self):
+        self.assertTrue(gsl.is_api_level_tag('introduced=24'))
+        self.assertTrue(gsl.is_api_level_tag('introduced-arm=24'))
+        self.assertTrue(gsl.is_api_level_tag('versioned=24'))
+
+        # Shouldn't try to process things that aren't a key/value tag.
+        self.assertFalse(gsl.is_api_level_tag('arm'))
+        self.assertFalse(gsl.is_api_level_tag('introduced'))
+        self.assertFalse(gsl.is_api_level_tag('versioned'))
+
+        # We don't support arch specific `versioned` tags.
+        self.assertFalse(gsl.is_api_level_tag('versioned-arm=24'))
+
+    def test_decode_api_level_tags(self):
+        api_map = {
+            'O': 9000,
+            'P': 9001,
+        }
+
+        tags = [
+            'introduced=9',
+            'introduced-arm=14',
+            'versioned=16',
+            'arm',
+            'introduced=O',
+            'introduced=P',
+        ]
+        expected_tags = [
+            'introduced=9',
+            'introduced-arm=14',
+            'versioned=16',
+            'arm',
+            'introduced=9000',
+            'introduced=9001',
+        ]
+        self.assertListEqual(
+            expected_tags, gsl.decode_api_level_tags(tags, api_map))
+
+        with self.assertRaises(gsl.ParseError):
+            gsl.decode_api_level_tags(['introduced=O'], {})
+
 
 class PrivateVersionTest(unittest.TestCase):
     def test_version_is_private(self):
@@ -151,7 +207,7 @@
             # baz
             qux
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         self.assertIsNone(parser.current_line)
 
         self.assertEqual('foo', parser.next_line().strip())
@@ -176,7 +232,7 @@
             VERSION_2 {
             } VERSION_1; # asdf
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
 
         parser.next_line()
         version = parser.parse_version()
@@ -200,7 +256,7 @@
         input_file = cStringIO.StringIO(textwrap.dedent("""\
             VERSION_1 {
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
@@ -211,7 +267,7 @@
                 foo:
             }
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
@@ -221,7 +277,7 @@
             foo;
             bar; # baz qux
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
 
         parser.next_line()
         symbol = parser.parse_symbol()
@@ -239,7 +295,7 @@
                 *;
             };
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
@@ -251,7 +307,7 @@
                     *;
             };
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         parser.next_line()
         version = parser.parse_version()
         self.assertEqual([], version.symbols)
@@ -262,7 +318,7 @@
                 foo
             };
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         parser.next_line()
         with self.assertRaises(gsl.ParseError):
             parser.parse_version()
@@ -270,7 +326,7 @@
     def test_parse_fails_invalid_input(self):
         with self.assertRaises(gsl.ParseError):
             input_file = cStringIO.StringIO('foo')
-            parser = gsl.SymbolFileParser(input_file)
+            parser = gsl.SymbolFileParser(input_file, {})
             parser.parse()
 
     def test_parse(self):
@@ -291,7 +347,7 @@
                     qwerty;
             } VERSION_1;
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, {})
         versions = parser.parse()
 
         expected = [
@@ -408,11 +464,18 @@
 
 class IntegrationTest(unittest.TestCase):
     def test_integration(self):
+        api_map = {
+            'O': 9000,
+            'P': 9001,
+        }
+
         input_file = cStringIO.StringIO(textwrap.dedent("""\
             VERSION_1 {
                 global:
                     foo; # var
                     bar; # x86
+                    fizz; # introduced=O
+                    buzz; # introduced=P
                 local:
                     *;
             };
@@ -436,7 +499,7 @@
                 wobble;
             } VERSION_4;
         """))
-        parser = gsl.SymbolFileParser(input_file)
+        parser = gsl.SymbolFileParser(input_file, api_map)
         versions = parser.parse()
 
         src_file = cStringIO.StringIO()
@@ -469,6 +532,46 @@
         """)
         self.assertEqual(expected_version, version_file.getvalue())
 
+    def test_integration_future_api(self):
+        api_map = {
+            'O': 9000,
+            'P': 9001,
+            'Q': 9002,
+        }
+
+        input_file = cStringIO.StringIO(textwrap.dedent("""\
+            VERSION_1 {
+                global:
+                    foo; # introduced=O
+                    bar; # introduced=P
+                    baz; # introduced=Q
+                local:
+                    *;
+            };
+        """))
+        parser = gsl.SymbolFileParser(input_file, api_map)
+        versions = parser.parse()
+
+        src_file = cStringIO.StringIO()
+        version_file = cStringIO.StringIO()
+        generator = gsl.Generator(src_file, version_file, 'arm', 9001, False)
+        generator.write(versions)
+
+        expected_src = textwrap.dedent("""\
+            void foo() {}
+            void bar() {}
+        """)
+        self.assertEqual(expected_src, src_file.getvalue())
+
+        expected_version = textwrap.dedent("""\
+            VERSION_1 {
+                global:
+                    foo;
+                    bar;
+            };
+        """)
+        self.assertEqual(expected_version, version_file.getvalue())
+
 
 def main():
     suite = unittest.TestLoader().loadTestsFromName(__name__)