tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_generate_static_pref_list.py (11438B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 import sys
      6 import unittest
      7 from os import path
      8 
      9 import mozpack.path as mozpath
     10 import mozunit
     11 import yaml
     12 
     13 try:
     14    from StringIO import StringIO
     15 except ImportError:
     16    from io import StringIO
     17 
     18 sys.path.append(path.join(path.dirname(__file__), ".."))
     19 from init.generate_static_pref_list import check_pref_list, generate_code
     20 
     21 test_data_path = mozpath.abspath(mozpath.dirname(__file__))
     22 test_data_path = mozpath.join(test_data_path, "data")
     23 
     24 # A single good input with lots of different combinations.
     25 good_input = """
     26 - name: my.bool
     27  type: bool
     28  value: false
     29  mirror: never
     30 
     31 - name: my.int
     32  type: int32_t
     33  value: -123
     34  mirror: once
     35  do_not_use_directly: false
     36  rust: false
     37 
     38 - mirror: always
     39  value: 999
     40  type: uint32_t
     41  name: my.uint
     42  rust: true
     43 
     44 - name: my.float            # A comment.
     45  type: float               # A comment.
     46  do_not_use_directly: true # A comment.
     47  value: 0.0f               # A comment.
     48  mirror: once              # A comment.
     49  rust: true                # A comment.
     50 
     51 # A comment.
     52 - name: my.string
     53  type: String
     54  value: foo"bar    # The double quote needs escaping.
     55  mirror: never
     56  include: foobar.h
     57 
     58 # A comment.
     59 - name: my.string2
     60  type: String
     61  value: "foobar"    # This string is quoted.
     62  mirror: never
     63 
     64 # A comment.
     65 - name: my.atomic.bool
     66  type: RelaxedAtomicBool
     67  value: true
     68  mirror: always
     69  rust: true
     70 
     71 # A comment.
     72 - name: my.datamutex.string
     73  type: DataMutexString
     74  value: "foobar"    # This string is quoted.
     75  mirror: always
     76 
     77 # Mirrored string-valued prefs are interesting in Rust.
     78 - name: my.datamutex.string.rust
     79  type: DataMutexString
     80  value: ""
     81  mirror: always
     82  rust: true
     83 
     84 # YAML+Python interprets `10 + 10 * 20` as a string, and so it is printed
     85 # unchanged.
     86 - name: my.atomic.int
     87  type: ReleaseAcquireAtomicInt32
     88  value: 10 + 10 * 20
     89  mirror: always
     90  do_not_use_directly: true # A comment.
     91 
     92 # YAML+Python changes `0x44` to `68` because it interprets the value as an
     93 # integer.
     94 - name: my.atomic.uint
     95  type: SequentiallyConsistentAtomicUint32
     96  value: 0x44
     97  mirror: once
     98 
     99 # YAML+Python changes `.4455667` to `0.4455667` because it interprets the value
    100 # as a float.
    101 - name: my-dashed.atomic.float
    102  type: AtomicFloat
    103  value: .4455667
    104  mirror: never
    105  include: <math.h>
    106 """
    107 
    108 # The corresponding code for good_input.
    109 good = {}
    110 
    111 good["static_pref_list_all_h"] = """\
    112 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    113 
    114 #include "mozilla/StaticPrefList_my.h"
    115 #include "mozilla/StaticPrefList_my_dashed.h"
    116 """
    117 
    118 good["static_prefs_all_h"] = """\
    119 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    120 
    121 #include "mozilla/StaticPrefs_my.h"
    122 #include "mozilla/StaticPrefs_my_dashed.h"
    123 """
    124 
    125 good["static_pref_list_group_h"] = {
    126    "my": """\
    127 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    128 
    129 NEVER_PREF("my.bool", bool, false)
    130 
    131 ONCE_PREF(
    132  "my.int",
    133   my_int,
    134   my_int_AtStartup,
    135  int32_t, -123
    136 )
    137 
    138 ALWAYS_PREF(
    139  "my.uint",
    140   my_uint,
    141   my_uint,
    142  uint32_t, 999
    143 )
    144 
    145 ONCE_PREF(
    146  "my.float",
    147   my_float,
    148   my_float_AtStartup_DoNotUseDirectly,
    149  float, 0.0f
    150 )
    151 
    152 NEVER_PREF("my.string", String, "foo\\"bar")
    153 
    154 NEVER_PREF("my.string2", String, "foobar")
    155 
    156 ALWAYS_PREF(
    157  "my.atomic.bool",
    158   my_atomic_bool,
    159   my_atomic_bool,
    160  RelaxedAtomicBool, true
    161 )
    162 
    163 ALWAYS_DATAMUTEX_PREF(
    164  "my.datamutex.string",
    165   my_datamutex_string,
    166   my_datamutex_string,
    167  DataMutexString, "foobar"_ns
    168 )
    169 
    170 ALWAYS_DATAMUTEX_PREF(
    171  "my.datamutex.string.rust",
    172   my_datamutex_string_rust,
    173   my_datamutex_string_rust,
    174  DataMutexString, ""_ns
    175 )
    176 
    177 ALWAYS_PREF(
    178  "my.atomic.int",
    179   my_atomic_int,
    180   my_atomic_int_DoNotUseDirectly,
    181  ReleaseAcquireAtomicInt32, 10 + 10 * 20
    182 )
    183 
    184 ONCE_PREF(
    185  "my.atomic.uint",
    186   my_atomic_uint,
    187   my_atomic_uint_AtStartup,
    188  SequentiallyConsistentAtomicUint32, 68
    189 )
    190 """,
    191    "my_dashed": """\
    192 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    193 
    194 NEVER_PREF("my-dashed.atomic.float", AtomicFloat, 0.4455667)
    195 """,
    196 }
    197 
    198 good["static_prefs_group_h"] = {
    199    "my": """\
    200 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    201 // Include it to gain access to StaticPrefs::my_*.
    202 
    203 #ifndef mozilla_StaticPrefs_my_h
    204 #define mozilla_StaticPrefs_my_h
    205 
    206 #include "foobar.h"
    207 
    208 #include "mozilla/StaticPrefListBegin.h"
    209 #include "mozilla/StaticPrefList_my.h"
    210 #include "mozilla/StaticPrefListEnd.h"
    211 
    212 #endif  // mozilla_StaticPrefs_my_h
    213 """
    214 }
    215 
    216 good["static_prefs_c_getters_cpp"] = """\
    217 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    218 
    219 extern "C" uint32_t StaticPrefs_my_uint() {
    220  return mozilla::StaticPrefs::my_uint();
    221 }
    222 
    223 extern "C" float StaticPrefs_my_float_AtStartup_DoNotUseDirectly() {
    224  return mozilla::StaticPrefs::my_float_AtStartup_DoNotUseDirectly();
    225 }
    226 
    227 extern "C" bool StaticPrefs_my_atomic_bool() {
    228  return mozilla::StaticPrefs::my_atomic_bool();
    229 }
    230 
    231 extern "C" void StaticPrefs_my_datamutex_string_rust(nsACString *result) {
    232  const auto preflock = mozilla::StaticPrefs::my_datamutex_string_rust();
    233  result->Append(*preflock);
    234 }
    235 """
    236 
    237 good["static_prefs_rs"] = """\
    238 // This file was generated by generate_static_pref_list.py from (string input). DO NOT EDIT.
    239 
    240 pub use nsstring::nsCString;
    241 extern "C" {
    242    pub fn StaticPrefs_my_uint() -> u32;
    243    pub fn StaticPrefs_my_float_AtStartup_DoNotUseDirectly() -> f32;
    244    pub fn StaticPrefs_my_atomic_bool() -> bool;
    245    pub fn StaticPrefs_my_datamutex_string_rust(result: *mut nsstring::nsACString);
    246 }
    247 
    248 #[macro_export]
    249 macro_rules! pref {
    250    ("my.uint") => (unsafe { $crate::StaticPrefs_my_uint() });
    251    ("my.float") => (unsafe { $crate::StaticPrefs_my_float_AtStartup_DoNotUseDirectly() });
    252    ("my.atomic.bool") => (unsafe { $crate::StaticPrefs_my_atomic_bool() });
    253    ("my.datamutex.string.rust") => (unsafe { let mut result = $crate::nsCString::new(); $crate::StaticPrefs_my_datamutex_string_rust(&mut *result); result });
    254 }
    255 """
    256 
    257 # A lot of bad inputs, each with an accompanying error message. Listed in order
    258 # of the relevant `error` calls within generate_static_pref_list.py.
    259 bad_inputs = [
    260    (
    261        """
    262 - invalidkey: 3
    263 """,
    264        "invalid key `invalidkey`",
    265    ),
    266    (
    267        """
    268 - type: int32_t
    269 """,
    270        "missing `name` key",
    271    ),
    272    (
    273        """
    274 - name: 99
    275 """,
    276        "non-string `name` value `99`",
    277    ),
    278    (
    279        """
    280 - name: name_with_no_dot
    281 """,
    282        "`name` value `name_with_no_dot` lacks a '.'",
    283    ),
    284    (
    285        """
    286 - name: pref.is.defined.more.than.once
    287  type: bool
    288  value: false
    289  mirror: never
    290 - name: pref.is.defined.more.than.once
    291  type: int32_t
    292  value: 111
    293  mirror: always
    294 """,
    295        "`pref.is.defined.more.than.once` pref is defined more than once",
    296    ),
    297    (
    298        """
    299 - name: your.pref
    300  type: bool
    301  value: false
    302  mirror: never
    303 - name: my.pref
    304  type: bool
    305  value: false
    306  mirror: never
    307 """,
    308        "`my.pref` pref must come before `your.pref` pref",
    309    ),
    310    (
    311        """
    312 - name: missing.type.key
    313  value: false
    314  mirror: never
    315 """,
    316        "missing `type` key for pref `missing.type.key`",
    317    ),
    318    (
    319        """
    320 - name: invalid.type.value
    321  type: const char*
    322  value: true
    323  mirror: never
    324 """,
    325        "invalid `type` value `const char*` for pref `invalid.type.value`",
    326    ),
    327    (
    328        """
    329 - name: missing.value.key
    330  type: int32_t
    331  mirror: once
    332 """,
    333        "missing `value` key for pref `missing.value.key`",
    334    ),
    335    (
    336        """
    337 - name: non-string.value
    338  type: String
    339  value: 3.45
    340  mirror: once
    341 """,
    342        "non-string `value` value `3.45` for `String` pref `non-string.value`; add double quotes",
    343    ),
    344    (
    345        """
    346 - name: invalid.boolean.value
    347  type: bool
    348  value: true || false
    349  mirror: once
    350 """,
    351        "invalid boolean value `true || false` for pref `invalid.boolean.value`",
    352    ),
    353    (
    354        """
    355 - name: missing.mirror.key
    356  type: int32_t
    357  value: 3
    358 """,
    359        "missing `mirror` key for pref `missing.mirror.key`",
    360    ),
    361    (
    362        """
    363 - name: invalid.mirror.value
    364  type: bool
    365  value: true
    366  mirror: sometimes
    367 """,
    368        "invalid `mirror` value `sometimes` for pref `invalid.mirror.value`",
    369    ),
    370    (
    371        """
    372 - name: non-boolean.do_not_use_directly.value
    373  type: bool
    374  value: true
    375  mirror: always
    376  do_not_use_directly: 0
    377 """,
    378        "non-boolean `do_not_use_directly` value `0` for pref "
    379        "`non-boolean.do_not_use_directly.value`",
    380    ),
    381    (
    382        """
    383 - name: do_not_use_directly.uselessly.set
    384  type: int32_t
    385  value: 0
    386  mirror: never
    387  do_not_use_directly: true
    388 """,
    389        "`do_not_use_directly` uselessly set with `mirror` value `never` for "
    390        "pref `do_not_use_directly.uselessly.set`",
    391    ),
    392    (
    393        """
    394 - name: non-string.include.value
    395  type: bool
    396  value: true
    397  mirror: always
    398  include: 33
    399 """,
    400        "non-string `include` value `33` for pref `non-string.include.value`",
    401    ),
    402    (
    403        """
    404 - name: include.value.starts.with
    405  type: float
    406  value: M_PI
    407  mirror: never
    408  include: <cmath
    409 """,
    410        "`include` value `<cmath` starts with `<` but does not end with `>` for "
    411        "pref `include.value.starts.with`",
    412    ),
    413    (
    414        """
    415 - name: non-boolean.rust.value
    416  type: bool
    417  value: true
    418  mirror: always
    419  rust: 1
    420 """,
    421        "non-boolean `rust` value `1` for pref `non-boolean.rust.value`",
    422    ),
    423    (
    424        """
    425 - name: rust.uselessly.set
    426  type: int32_t
    427  value: 0
    428  mirror: never
    429  rust: true
    430 """,
    431        "`rust` uselessly set with `mirror` value `never` for pref "
    432        "`rust.uselessly.set`",
    433    ),
    434 ]
    435 
    436 
    437 class TestGenerateStaticPrefList(unittest.TestCase):
    438    """
    439    Unit tests for generate_static_pref_list.py.
    440    """
    441 
    442    def test_good(self):
    443        "Test various pieces of good input."
    444        inp = StringIO(good_input)
    445        pref_list = yaml.safe_load(inp)
    446        check_pref_list(pref_list)
    447        code = generate_code(pref_list, ["(string input)"])
    448 
    449        self.assertEqual(good["static_pref_list_all_h"], code["static_pref_list_all_h"])
    450 
    451        self.assertEqual(good["static_prefs_all_h"], code["static_prefs_all_h"])
    452 
    453        self.assertEqual(
    454            good["static_pref_list_group_h"]["my"],
    455            code["static_pref_list_group_h"]["my"],
    456        )
    457        self.assertEqual(
    458            good["static_pref_list_group_h"]["my_dashed"],
    459            code["static_pref_list_group_h"]["my_dashed"],
    460        )
    461 
    462        self.assertEqual(
    463            good["static_prefs_group_h"]["my"], code["static_prefs_group_h"]["my"]
    464        )
    465 
    466        self.assertEqual(
    467            good["static_prefs_c_getters_cpp"], code["static_prefs_c_getters_cpp"]
    468        )
    469 
    470        self.assertEqual(good["static_prefs_rs"], code["static_prefs_rs"])
    471 
    472    def test_bad(self):
    473        "Test various pieces of bad input."
    474 
    475        for input_string, expected in bad_inputs:
    476            inp = StringIO(input_string)
    477            try:
    478                pref_list = yaml.safe_load(inp)
    479                check_pref_list(pref_list)
    480                generate_code(pref_list, ["(string input"])
    481                self.assertEqual(0, 1)
    482            except ValueError as e:
    483                self.assertEqual(str(e), expected)
    484 
    485 
    486 if __name__ == "__main__":
    487    mozunit.main()