| 1 | #!/usr/bin/env python2
 | 
| 2 | # coding=utf8
 | 
| 3 | 
 | 
| 4 | import os
 | 
| 5 | import unittest
 | 
| 6 | 
 | 
| 7 | from core import ansi
 | 
| 8 | from core import ui
 | 
| 9 | from data_lang import j8
 | 
| 10 | from data_lang import pretty  # module under test
 | 
| 11 | from mycpp import mylib
 | 
| 12 | from typing import Optional
 | 
| 13 | 
 | 
| 14 | import libc
 | 
| 15 | 
 | 
| 16 | TEST_DATA_FILENAME = os.path.join(os.path.dirname(__file__), "pretty_test.txt")
 | 
| 17 | 
 | 
| 18 | 
 | 
| 19 | def _PrintCase(actual, expected, lineno=None):
 | 
| 20 |     if actual != expected:
 | 
| 21 |         # Print the different with real newlines, for easier reading.
 | 
| 22 |         print("ACTUAL:")
 | 
| 23 |         print(actual)
 | 
| 24 |         print("EXPECTED:")
 | 
| 25 |         print(expected)
 | 
| 26 |         print("END")
 | 
| 27 |         if lineno is not None:
 | 
| 28 |             print("ON LINE " + str(lineno + 1))
 | 
| 29 | 
 | 
| 30 | 
 | 
| 31 | class UiTest(unittest.TestCase):
 | 
| 32 |     """Test higher level ui.PrettyPrintValue()."""
 | 
| 33 | 
 | 
| 34 |     def assertPretty(self, width, value_str, expected):
 | 
| 35 |         # type: (int, str, str, Optional[int]) -> None
 | 
| 36 |         parser = j8.Parser(value_str, True)
 | 
| 37 |         val = parser.ParseValue()
 | 
| 38 | 
 | 
| 39 |         buf = mylib.BufWriter()
 | 
| 40 |         ui.PrettyPrintValue('', val, buf, max_width=width)
 | 
| 41 | 
 | 
| 42 |         actual = buf.getvalue()
 | 
| 43 |         _PrintCase(actual, expected)
 | 
| 44 |         self.assertEqual(actual, expected)
 | 
| 45 | 
 | 
| 46 |     def testTypePrefix(self):
 | 
| 47 |         self.assertPretty(25, '[null, "ok", 15]',
 | 
| 48 |                           "(List)   [null, 'ok', 15]\n")
 | 
| 49 |         self.assertPretty(24, '[null, "ok", 15]', "(List)\n[null, 'ok', 15]\n")
 | 
| 50 | 
 | 
| 51 | 
 | 
| 52 | class PrettyTest(unittest.TestCase):
 | 
| 53 | 
 | 
| 54 |     def setUp(self):
 | 
| 55 |         # Use settings that make testing easier.
 | 
| 56 |         self.encoder = pretty.ValueEncoder()
 | 
| 57 |         self.encoder.SetUseStyles(False)
 | 
| 58 | 
 | 
| 59 |     def assertPretty(self, width, value_str, expected, lineno=None):
 | 
| 60 |         # type: (int, str, str, Optional[int]) -> None
 | 
| 61 |         parser = j8.Parser(value_str, True)
 | 
| 62 |         val = parser.ParseValue()
 | 
| 63 | 
 | 
| 64 |         buf = mylib.BufWriter()
 | 
| 65 | 
 | 
| 66 |         doc = self.encoder.Value(val)
 | 
| 67 | 
 | 
| 68 |         printer = pretty.PrettyPrinter(width)
 | 
| 69 |         printer.PrintDoc(doc, buf)
 | 
| 70 | 
 | 
| 71 |         actual = buf.getvalue()
 | 
| 72 |         _PrintCase(actual, expected, lineno=lineno)
 | 
| 73 |         self.assertEqual(actual, expected)
 | 
| 74 | 
 | 
| 75 |     def testsFromFile(self):
 | 
| 76 |         # TODO: convert tests to this new style
 | 
| 77 |         self.encoder.ysh_style = False
 | 
| 78 | 
 | 
| 79 |         chunks = [(None, -1, [])]
 | 
| 80 |         for lineno, line in enumerate(
 | 
| 81 |                 open(TEST_DATA_FILENAME).read().splitlines()):
 | 
| 82 |             if line.startswith("> "):
 | 
| 83 |                 chunks[-1][2].append(line[2:])
 | 
| 84 |             elif line.startswith("#"):
 | 
| 85 |                 pass
 | 
| 86 |             elif line.strip() == "":
 | 
| 87 |                 pass
 | 
| 88 |             else:
 | 
| 89 |                 for keyword in ["Width", "Input", "Expect"]:
 | 
| 90 |                     if line.startswith(keyword):
 | 
| 91 |                         if chunks[-1][0] != keyword:
 | 
| 92 |                             chunks.append((keyword, lineno, []))
 | 
| 93 |                         parts = line.split(" > ", 1)
 | 
| 94 |                         if len(parts) == 2:
 | 
| 95 |                             chunks[-1][2].append(parts[1])
 | 
| 96 |                         break
 | 
| 97 |                 else:
 | 
| 98 |                     raise Exception(
 | 
| 99 |                         "Invalid pretty printing test case line. Lines must start with one of: Width, Input, Expect, >, #",
 | 
| 100 |                         line)
 | 
| 101 | 
 | 
| 102 |         test_cases = []
 | 
| 103 |         width = 80
 | 
| 104 |         value = ""
 | 
| 105 |         for (keyword, lineno, lines) in chunks:
 | 
| 106 |             block = "\n".join(lines)
 | 
| 107 |             if keyword == "Width":
 | 
| 108 |                 width = int(block)
 | 
| 109 |             elif keyword == "Input":
 | 
| 110 |                 value = block
 | 
| 111 |             elif keyword == "Expect":
 | 
| 112 |                 test_cases.append((width, value, block, lineno))
 | 
| 113 |             else:
 | 
| 114 |                 pass
 | 
| 115 | 
 | 
| 116 |         for (width, value, expected, lineno) in test_cases:
 | 
| 117 |             self.assertPretty(width, value, expected, lineno)
 | 
| 118 | 
 | 
| 119 |     def testStyles(self):
 | 
| 120 |         self.encoder.SetUseStyles(True)
 | 
| 121 |         self.assertPretty(
 | 
| 122 |             20, '[null, "ok", 15]',
 | 
| 123 |             '[' + ansi.RED + 'null' + ansi.RESET + ", " + ansi.GREEN + "'ok'" +
 | 
| 124 |             ansi.RESET + ", " + ansi.YELLOW + '15' + ansi.RESET + ']')
 | 
| 125 | 
 | 
| 126 | 
 | 
| 127 | if __name__ == '__main__':
 | 
| 128 |     # To simulate the OVM_MAIN patch in pythonrun.c
 | 
| 129 |     libc.cpython_reset_locale()
 | 
| 130 |     unittest.main()
 |