浏览代码

unit_test: Restore 'waf test' functionality

Signed-off-by: Colin Suckow <colin@suckow.dev>
Colin Suckow 4 月之前
父节点
当前提交
44e7092afb

+ 73 - 0
.github/workflows/test.yml

@@ -0,0 +1,73 @@
+name: Test
+
+on:
+  push:
+    branches: [main]
+  pull_request:
+    branches: [main]
+
+env:
+  ARM_GNU_TOOLCHAIN_VERSION: 14.2.rel1
+  EM_VERSION: 4.0.1
+  EM_CACHE_FOLDER: 'emsdk-cache'
+  TEST_BOARD: 'snowy_bb2'
+
+jobs:
+  build:
+    runs-on: ubuntu-24.04
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+          submodules: true
+
+      - name: Setup emsdk cache
+        id: cache-emsdk
+        uses: actions/cache@v4
+        with:
+          path: ${{env.EM_CACHE_FOLDER}}
+          key: emsdk-${{env.EM_VERSION}}-${{ runner.os }}
+
+      - uses: actions/setup-python@v5
+        with:
+          python-version: "3.13"
+
+      - name: Set up environment
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y gettext gcc-multilib
+          pip install -r requirements-linux.txt
+          pip install -e \
+            python_libs/pblprog \
+            python_libs/pebble-commander \
+            python_libs/pulse2 \
+            python_libs/pebble-loghash
+          wget --no-verbose "https://developer.arm.com/-/media/Files/downloads/gnu/${ARM_GNU_TOOLCHAIN_VERSION}/binrel/arm-gnu-toolchain-${ARM_GNU_TOOLCHAIN_VERSION}-x86_64-arm-none-eabi.tar.xz"
+          sudo tar xf arm-gnu-toolchain-${ARM_GNU_TOOLCHAIN_VERSION}-x86_64-arm-none-eabi.tar.xz -C /opt
+          echo "/opt/arm-gnu-toolchain-${ARM_GNU_TOOLCHAIN_VERSION}-x86_64-arm-none-eabi/bin" >> $GITHUB_PATH
+
+      - uses: mymindstorm/setup-emsdk@v14
+        with:
+          version: ${{env.EM_VERSION}}
+          actions-cache-folder: ${{env.EM_CACHE_FOLDER}}
+
+      - name: Configure
+        run: ./waf configure --board ${{env.TEST_BOARD}}
+
+      - name: Run tests
+        run: ./waf test
+        continue-on-error: true
+
+      - name: Publish Test Report
+        uses: mikepenz/action-junit-report@v5
+        if: success() || failure()
+        with:
+          report_paths: build/test/junit.xml
+          annotate_only: true
+
+      - name: Store failed test images
+        uses: actions/upload-artifact@v4
+        with:
+          name: failed_diff_images
+          path: build/test/tests/failed/*-diff.png

+ 1 - 1
tests/fakes/fake_kernel_services_notifications.c

@@ -34,7 +34,7 @@ void notifications_handle_notification_acted_upon(Uuid *id) {
   return;
 }
 
-void notifications_handle_notification_action_result() {
+void notifications_handle_notification_action_result(PebbleSysNotificationActionResult *action_result) {
 }
 
 void notifications_add_notification(TimelineItem *notification) {

+ 1 - 0
tests/fw/graphics/wscript

@@ -425,6 +425,7 @@ def build(ctx):
          ),
          test_sources_ant_glob="test_graphics_text_node.c")
 
+
     clar(ctx,
         sources_ant_glob =
             " src/fw/applib/graphics/perimeter.c"

+ 1 - 1
tests/fw/pebble_actions/wscript

@@ -35,7 +35,7 @@ def build(ctx):
         override_includes=['dummy_board'])
     
     clar(ctx,
-        sources_ant_glob = 
+        sources_ant_glob =
             "src/fw/services/normal/timeline/actions_endpoint.c " \
             "src/fw/services/normal/timeline/attribute.c " \
             "src/fw/services/normal/timeline/attribute_group.c " \

+ 1 - 0
tests/vendor/duma/wscript

@@ -14,6 +14,7 @@ def build(bld):
       defines.append('DUMA_SO_PREFER_GETENV')
 
     bld.stlib(source=['duma.c', 'print.c', 'sem_inc.c'],
+              cflags=['-Wno-unused-but-set-variable'], # Disabling a warning -Werror is tripping over
               defines=defines,
               target='duma')
 

+ 36 - 3
tests/wscript

@@ -279,9 +279,42 @@ def build(bld):
     # clang on Linux errors on true == true or false == false compile-time assertions
     bld.env.CFLAGS.append('-Wno-tautological-compare')
 
-    # time_t is defined in sys/types in newlib, and time.h on recent Linux
-    # so just force the defined type for testing time
-    bld.env.CFLAGS.append('-Dtime_t=__SYSCALL_SLONG_TYPE')
+    # Any test in this list won't be compiled
+    bld.env.BROKEN_TESTS = [
+        'test_app_fetch_endpoint.c',
+        'test_graphics_draw_text_flow.c',
+        'test_perimeter.c',
+        'test_ancs_pebble_actions.c',
+        'test_timeline_actions.c',
+        'test_bluetooth_persistent_storage_prf.c',
+        'test_bluetooth_persistent_storage.c',
+        'test_session.c',
+        'test_session_receive_router.c',
+        'test_compositor.c',
+        'test_floor.c',
+        'test_pow.c',
+        'test_ams.c',
+        'test_ams_util.c',
+        'test_gap_le_advert.c',
+        'test_bt_conn_mgr.c',
+        'test_gatt_client_accessors.c',
+        'test_gatt_client_discovery.c',
+        'test_gatt_client_subscriptions.c',
+        'test_gatt_service_changed_client.c',
+        'test_gatt_service_changed_server.c',
+        'test_gap_le_connect.c',
+        'test_ancs_util.c',
+        'test_ancs.c',
+        'test_kernel_le_client.c',
+        'test_ppogatt.c',
+        'test_graphics_circle.c'
+    ]
+
+    # Don't run the python tool tests because they exercise a lot of old python2 code that still needs to be updated
+    bld.env.PYTHON_TOOL_TESTS_DISABLED = True
+
+    # Disable warning promotion. Not ideal, but gets most of the tests running again without straight up disabling the new warnings
+    bld.env.CFLAGS.append('-Wno-error')
 
     # Many tests operate on a set of test images and require tools to process these
     # images and therefore need extra defines. Set up our environment first before running any

+ 1 - 1
tools/clar/_clar.py

@@ -61,7 +61,7 @@ def main():
     options, args = parser.parse_args()
 
     folder = args[0] or '.'
-    print 'folder: %s' % folder
+    print('folder: %s' % folder)
     builder = ClarTestBuilder(folder,
         clar_path = options.clar_path,
         print_mode = options.print_mode)

+ 2 - 2
tools/clar/clar.py

@@ -61,7 +61,7 @@ def main():
     options, args = parser.parse_args()
 
     folder = args[0] or '.'
-    print 'folder: %s' % folder
+    print('folder: %s' % folder)
     builder = ClarTestBuilder(folder,
         clar_path = options.clar_path,
         print_mode = options.print_mode)
@@ -112,7 +112,7 @@ class ClarTestBuilder:
                     self._process_test_file(test_name, f.read())
 
     def load_file(self, filename):
-        with open(filename) as f:
+        with open(filename, encoding="latin-1") as f:
           test_name = os.path.basename(filename)[:-2]
           self._process_test_file(test_name, f.read())
 

+ 1 - 1
tools/generate_pdcs/pdc_gen.py

@@ -95,7 +95,7 @@ def create_pdc_from_path(path, out_path, viewbox_size, verbose, duration, play_c
                 base = os.path.basename(path)
                 f = '.'.join(base.split('.')[:-1]) + '.pdc'
             out_path = os.path.join(dir_name, f)
-        with open(out_path, 'w') as out_file:
+        with open(out_path, 'wb') as out_file:
             out_file.write(output)
             out_file.close()
 

+ 5 - 5
tools/pbi2png.py

@@ -79,10 +79,10 @@ def pbi_to_png(pbi, pixel_bytearray):
             pixel_rgba_array.append(((argb8 >> 6) & 0x3) * 85)  # a
 
         png = Image.frombuffer('RGBA', (pbi.bounds_w, pbi.bounds_h),
-                               buffer(pixel_rgba_array), 'raw', 'RGBA', pbi.stride * 4, 1)
+                               memoryview(pixel_rgba_array), 'raw', 'RGBA', pbi.stride * 4, 1)
 
     elif gbitmap_version == 1 and pbi_is_palettized(gbitmap_format):
-        bitdepth = pbi_bitdepth(gbitmap_format)
+        bitdepth = int(pbi_bitdepth(gbitmap_format))
         print("{}-bit palettized color image".format(bitdepth))
 
         # Create palette colors in format R, G, B, A
@@ -96,12 +96,12 @@ def pbi_to_png(pbi, pixel_bytearray):
         # converting the depth-packed indexes for the palette to an unpacked list
         idx = 0  # index of actual packed values including padded values
         for pxl8 in pixel_bytearray[:palette_offset]:
-            for i in xrange(0, 8 / bitdepth):
+            for i in range(0, 8 // bitdepth):
                 # only append actual pixels, ignoring padding pixels
                 # which is the difference between the width and the stride
                 if (idx % (pbi.stride * (8 / bitdepth)) < pbi.bounds_w):
                     pixels.append(
-                        ((pxl8 >> (bitdepth * (8 / bitdepth - (i + 1)))) & ~(~0 << bitdepth)))
+                        ((pxl8 >> (bitdepth * (8 // bitdepth - (i + 1)))) & ~(~0 << bitdepth)))
                 idx = idx + 1
 
         # Manually convert from paletted to RGBA
@@ -124,7 +124,7 @@ def pbi_to_png(pbi, pixel_bytearray):
         png = Image.frombuffer('1', (pbi.bounds_w, pbi.bounds_h),
                                buffer(pixel_bytearray), 'raw', '1', pbi.stride, 1)
     else:
-        print "Bad PBI"
+        print("Bad PBI")
         png = None
 
     return png

+ 2 - 4
tools/pdc2png/wscript

@@ -51,9 +51,7 @@ def build(bld):
     pdc2png_env.CFLAGS.append('-I' + bld.path.abspath() + '/../src/fw/util/time')
     pdc2png_env.CFLAGS.append('-I' + bld.path.abspath() + '/src/include')
 
-    # time_t is defined in sys/types in newlib, and time.h on recent Linux
-    # so just force the defined type for testing time
-    pdc2png_env.CFLAGS.append('-Dtime_t=__SYSCALL_SLONG_TYPE')
+    pdc2png_env.CFLAGS.append('-Wno-gnu-variable-sized-type-not-at-end')
 
     pbi2png_script = bld.path.find_node('../pbi2png.py')
     pbi2png_copy = bld.path.get_bld().parent.parent.make_node('pbi2png.py')
@@ -67,7 +65,7 @@ def build(bld):
                          'DISP_COLS=144', 'DISP_ROWS=168',
                          'DISPLAY_FRAMEBUFFER_BYTES=%d' % (144 * 168),
                          'PBL_COLOR', 'PBL_RECT', 'PLATFORM_SNOWY=1',
-                         'PBI2PNG_EXE="pbi2png.py"'],
+                         'PBI2PNG_EXE="../../tools/pbi2png.py"'],
                 use=['libutil-32bit', 'libos_includes'],
                 env=pdc2png_env)
 

+ 2 - 0
tools/tests/wscript

@@ -1,4 +1,6 @@
 def build(bld):
+    if bld.env.PYTHON_TOOL_TESTS_DISABLED:
+        return
     tests = bld.path.ant_glob('test_*.py')
     bld(rule="python -m unittest discover -s {} -p 'test_*.py'".format(bld.path.abspath()),
         source=tests)

+ 11 - 7
waftools/pebble_test.py

@@ -36,7 +36,7 @@ def make_test(self):
         task = self.create_task('run_test', sources)
         runtime_deps = getattr(self.link_task.generator, 'runtime_deps', None)
         if runtime_deps is not None:
-            task.dep_nodes = runtime_deps
+            task.dep_nodes = list(runtime_deps)
 
 # Lock to prevent concurrent modifications of the utest_results list. We may
 # have multiple tests running and finishing at the same time.
@@ -140,12 +140,12 @@ def summary(bld):
         # FIXME: We don't get a status per test, only at the suite level...
         # Perhaps clar itself should do the reporting?
         def strip_non_ascii(s):
-            return "".join(i for i in s if ord(i) < 128)
+            return "".join(i for i in str(s) if ord(i) < 128)
         test_case = junit_xml.TestCase('all')
         if code:
             # Include stdout and stderr if test failed:
-            test_case.stdout = strip_non_ascii(stdout)
-            test_case.stderr = strip_non_ascii(stderr)
+            test_case.stdout = strip_non_ascii(stdout.decode("utf-8"))
+            test_case.stderr = strip_non_ascii(stderr.decode("utf-8"))
             test_case.add_failure_info(message='failed')
         suite_name = node.parent.relpath()
         test_suite = junit_xml.TestSuite(suite_name, [test_case])
@@ -169,8 +169,8 @@ def summary(bld):
             if code:
                 Logs.pprint('RED', '    %s' % node.abspath())
                 # FIXME: Make UTF-8 print properly, see PBL-29528
-                print(ud.normalize('NFKD', out.decode('utf-8')).encode('ascii', 'ignore'))
-                print(ud.normalize('NFKD', err.decode('utf-8')).encode('ascii', 'ignore'))
+                print(ud.normalize('NFKD', out.decode('utf-8')))
+                print(ud.normalize('NFKD', err.decode('utf-8')))
         raise Errors.WafError('test failed')
 
 @taskgen_method
@@ -212,7 +212,7 @@ def build_product_source_files(bld, test_dir, include_paths, defines, cflags, pr
     product_objects = []
     for s in product_sources:
         # Make sure everything in the list is a node
-        if isinstance(s, basestring):
+        if isinstance(s, str):
             src_node = bld.path.find_node(s)
         else:
             src_node = s
@@ -414,6 +414,10 @@ def clar(bld, sources=None, sources_ant_glob=None, test_sources_ant_glob=None,
     if test_sources_ant_glob is None and not test_sources:
         raise Exception()
 
+    if test_sources_ant_glob in bld.env.BROKEN_TESTS:
+        Logs.pprint('RED', f'Skipping glob because it is in the BROKEN_TESTS list: {test_sources_ant_glob}')
+        return
+
     if test_sources is None:
         test_sources = []
 

+ 1 - 1
wscript

@@ -726,8 +726,8 @@ def build(bld):
         bld.recurse('src/libbtutil')
         bld.recurse('src/libos')
         bld.recurse('src/libutil')
-        bld.recurse('tools')
         bld.recurse('tests')
+        bld.recurse('tools')
         return
     elif bld.variant == 'test_rocky_emx':
         if bld.env.APPLIB_TARGET != 'emscripten':