1cc1dc7a3Sopenharmony_ci#!/usr/bin/env python3
2cc1dc7a3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0
3cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
4cc1dc7a3Sopenharmony_ci# Copyright 2020-2023 Arm Limited
5cc1dc7a3Sopenharmony_ci#
6cc1dc7a3Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); you may not
7cc1dc7a3Sopenharmony_ci# use this file except in compliance with the License. You may obtain a copy
8cc1dc7a3Sopenharmony_ci# of the License at:
9cc1dc7a3Sopenharmony_ci#
10cc1dc7a3Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
11cc1dc7a3Sopenharmony_ci#
12cc1dc7a3Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
13cc1dc7a3Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14cc1dc7a3Sopenharmony_ci# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15cc1dc7a3Sopenharmony_ci# License for the specific language governing permissions and limitations
16cc1dc7a3Sopenharmony_ci# under the License.
17cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
18cc1dc7a3Sopenharmony_ci"""
19cc1dc7a3Sopenharmony_ciThe functional test runner is a set of tests that validate the ``astcenc``
20cc1dc7a3Sopenharmony_cicommand line is correctly handled, under both valid and invalid usage
21cc1dc7a3Sopenharmony_ciscenarios. These tests do NOT validate the compression codec itself, beyond
22cc1dc7a3Sopenharmony_cisome very basic incidental usage needed to validate the command line.
23cc1dc7a3Sopenharmony_ci
24cc1dc7a3Sopenharmony_ciDue to the need to validate pixel colors in test images for both LDR and HDR
25cc1dc7a3Sopenharmony_ciimages, these tests rely on an HDRI-enabled build of ImageMagic being available
26cc1dc7a3Sopenharmony_cion the system path. To test if the version of ImageMagic on your system is
27cc1dc7a3Sopenharmony_ciHDRI-enabled run:
28cc1dc7a3Sopenharmony_ci
29cc1dc7a3Sopenharmony_ci    convert --version
30cc1dc7a3Sopenharmony_ci
31cc1dc7a3Sopenharmony_ci... and check that the string "HDRI" is present in the listed features.
32cc1dc7a3Sopenharmony_ci
33cc1dc7a3Sopenharmony_ciTest Tiles
34cc1dc7a3Sopenharmony_ci==========
35cc1dc7a3Sopenharmony_ci
36cc1dc7a3Sopenharmony_ciSome basic test images, each 8x8 texels and built up from 4 no. 4x4 texel
37cc1dc7a3Sopenharmony_ciconstant color blocks, are used to help determine that the command line is
38cc1dc7a3Sopenharmony_cibeing processed correctly.
39cc1dc7a3Sopenharmony_ci
40cc1dc7a3Sopenharmony_ciLDR Test Pattern
41cc1dc7a3Sopenharmony_ci----------------
42cc1dc7a3Sopenharmony_ci
43cc1dc7a3Sopenharmony_ciLDR images are an 8x8 image containing 4 4x4 constant color blocks. Assuming
44cc1dc7a3Sopenharmony_ci(0, 0) is the top left (TL), the component uncompressed block colors are:
45cc1dc7a3Sopenharmony_ci
46cc1dc7a3Sopenharmony_ci* (0, 0) TL = Black, opaque = (0.00, 0.00, 0.00, 1.00)
47cc1dc7a3Sopenharmony_ci* (7, 0) TR = Red, opaque   = (1.00, 0.00, 0.00, 1.00)
48cc1dc7a3Sopenharmony_ci* (0, 7) BL = White, opaque = (1.00, 1.00, 1.00, 1.00)
49cc1dc7a3Sopenharmony_ci* (7, 7) BR = Green, trans  = (0.25, 0.75, 0.00, 0.87)
50cc1dc7a3Sopenharmony_ci
51cc1dc7a3Sopenharmony_ciHDR Test Pattern
52cc1dc7a3Sopenharmony_ci----------------
53cc1dc7a3Sopenharmony_ci
54cc1dc7a3Sopenharmony_ciHDR images are an 8x8 image containing 4 4x4 constant color blocks. Assuming
55cc1dc7a3Sopenharmony_ci(0, 0) is the top left (TL), the component uncompressed block colors are:
56cc1dc7a3Sopenharmony_ci
57cc1dc7a3Sopenharmony_ci* (0, 0) TL = LDR Black, opaque = (0.00, 0.00, 0.00, 1.00)
58cc1dc7a3Sopenharmony_ci* (7, 0) TR = HDR Red, opaque   = (8.00, 0.00, 0.00, 1.00)
59cc1dc7a3Sopenharmony_ci* (0, 7) BL = HDR White, opaque = (3.98, 3.98, 3.98, 1.00)
60cc1dc7a3Sopenharmony_ci* (7, 7) BR = LDR Green, trans  = (0.25, 0.75, 0.00, 0.87)
61cc1dc7a3Sopenharmony_ci"""
62cc1dc7a3Sopenharmony_ci
63cc1dc7a3Sopenharmony_ciimport argparse
64cc1dc7a3Sopenharmony_ciimport filecmp
65cc1dc7a3Sopenharmony_ciimport os
66cc1dc7a3Sopenharmony_ciimport re
67cc1dc7a3Sopenharmony_ciimport signal
68cc1dc7a3Sopenharmony_ciimport string
69cc1dc7a3Sopenharmony_ciimport subprocess as sp
70cc1dc7a3Sopenharmony_ciimport sys
71cc1dc7a3Sopenharmony_ciimport tempfile
72cc1dc7a3Sopenharmony_ciimport time
73cc1dc7a3Sopenharmony_ciimport unittest
74cc1dc7a3Sopenharmony_ci
75cc1dc7a3Sopenharmony_ciimport numpy
76cc1dc7a3Sopenharmony_cifrom PIL import Image
77cc1dc7a3Sopenharmony_ci
78cc1dc7a3Sopenharmony_ciimport testlib.encoder as te
79cc1dc7a3Sopenharmony_ciimport testlib.image as tli
80cc1dc7a3Sopenharmony_ci
81cc1dc7a3Sopenharmony_ci# Enable these to always write out, irrespective of test result
82cc1dc7a3Sopenharmony_ciASTCENC_CLI_ALWAYS = False
83cc1dc7a3Sopenharmony_ciASTCENC_LOG_ALWAYS = False
84cc1dc7a3Sopenharmony_ci
85cc1dc7a3Sopenharmony_ci# Enable these to write out on failure for positive tests
86cc1dc7a3Sopenharmony_ciASTCENC_CLI_ON_ERROR = True
87cc1dc7a3Sopenharmony_ciASTCENC_LOG_ON_ERROR = True
88cc1dc7a3Sopenharmony_ci
89cc1dc7a3Sopenharmony_ci# Enable these to write out on failure for negative tests
90cc1dc7a3Sopenharmony_ciASTCENC_CLI_ON_ERROR_NEG = True
91cc1dc7a3Sopenharmony_ciASTCENC_LOG_ON_ERROR_NEG = True
92cc1dc7a3Sopenharmony_ci
93cc1dc7a3Sopenharmony_ci# LDR test pattern
94cc1dc7a3Sopenharmony_ciASTCENC_TEST_PATTERN_LDR = {
95cc1dc7a3Sopenharmony_ci    "TL": (0.00, 0.00, 0.00, 1.00),
96cc1dc7a3Sopenharmony_ci    "TR": (1.00, 0.00, 0.00, 1.00),
97cc1dc7a3Sopenharmony_ci    "BL": (1.00, 1.00, 1.00, 1.00),
98cc1dc7a3Sopenharmony_ci    "BR": (0.25, 0.75, 0.00, 0.87)
99cc1dc7a3Sopenharmony_ci}
100cc1dc7a3Sopenharmony_ci
101cc1dc7a3Sopenharmony_ci# HDR test pattern
102cc1dc7a3Sopenharmony_ciASTCENC_TEST_PATTERN_HDR = {
103cc1dc7a3Sopenharmony_ci    "TL": (0.00, 0.00, 0.00, 1.00),
104cc1dc7a3Sopenharmony_ci    "TR": (8.00, 0.00, 0.00, 1.00),
105cc1dc7a3Sopenharmony_ci    "BL": (3.98, 3.98, 3.98, 1.00),
106cc1dc7a3Sopenharmony_ci    "BR": (0.25, 0.75, 0.00, 0.87)
107cc1dc7a3Sopenharmony_ci}
108cc1dc7a3Sopenharmony_ci
109cc1dc7a3Sopenharmony_ciLDR_RGB_PSNR_PATTERN = re.compile(r"\s*PSNR \(LDR-RGB\): (.*) dB")
110cc1dc7a3Sopenharmony_ci
111cc1dc7a3Sopenharmony_cig_TestEncoder = "avx2"
112cc1dc7a3Sopenharmony_ci
113cc1dc7a3Sopenharmony_ciclass CLITestBase(unittest.TestCase):
114cc1dc7a3Sopenharmony_ci    """
115cc1dc7a3Sopenharmony_ci    Command line interface base class.
116cc1dc7a3Sopenharmony_ci
117cc1dc7a3Sopenharmony_ci    These tests are designed to test the command line is handled correctly.
118cc1dc7a3Sopenharmony_ci    They are not detailed tests of the codec itself; only basic sanity checks
119cc1dc7a3Sopenharmony_ci    that some type of processing occurred are used.
120cc1dc7a3Sopenharmony_ci    """
121cc1dc7a3Sopenharmony_ci
122cc1dc7a3Sopenharmony_ci    def __init__(self, *args, **kwargs):
123cc1dc7a3Sopenharmony_ci        super().__init__(*args, **kwargs)
124cc1dc7a3Sopenharmony_ci
125cc1dc7a3Sopenharmony_ci        encoder = te.Encoder2x(g_TestEncoder)
126cc1dc7a3Sopenharmony_ci        self.binary = encoder.binary
127cc1dc7a3Sopenharmony_ci
128cc1dc7a3Sopenharmony_ci    def setUp(self):
129cc1dc7a3Sopenharmony_ci        """
130cc1dc7a3Sopenharmony_ci        Set up a test case.
131cc1dc7a3Sopenharmony_ci
132cc1dc7a3Sopenharmony_ci        Create a new temporary directory for output files.
133cc1dc7a3Sopenharmony_ci        """
134cc1dc7a3Sopenharmony_ci        self.tempDir = tempfile.TemporaryDirectory()
135cc1dc7a3Sopenharmony_ci
136cc1dc7a3Sopenharmony_ci    def tearDown(self):
137cc1dc7a3Sopenharmony_ci        """
138cc1dc7a3Sopenharmony_ci        Tear down a test case.
139cc1dc7a3Sopenharmony_ci
140cc1dc7a3Sopenharmony_ci        Clean up the temporary directory created for output files.
141cc1dc7a3Sopenharmony_ci        """
142cc1dc7a3Sopenharmony_ci        self.tempDir.cleanup()
143cc1dc7a3Sopenharmony_ci        self.tempDir = None
144cc1dc7a3Sopenharmony_ci
145cc1dc7a3Sopenharmony_ci    @staticmethod
146cc1dc7a3Sopenharmony_ci    def get_ref_image_path(profile, mode, image):
147cc1dc7a3Sopenharmony_ci        """
148cc1dc7a3Sopenharmony_ci        Get the path of a reference image on disk.
149cc1dc7a3Sopenharmony_ci
150cc1dc7a3Sopenharmony_ci        Args:
151cc1dc7a3Sopenharmony_ci            profile (str): The color profile.
152cc1dc7a3Sopenharmony_ci            mode (str): The type of image to load.
153cc1dc7a3Sopenharmony_ci            image (str): The image variant to load.
154cc1dc7a3Sopenharmony_ci
155cc1dc7a3Sopenharmony_ci        Returns:
156cc1dc7a3Sopenharmony_ci            str: The path to the test image file on disk.
157cc1dc7a3Sopenharmony_ci        """
158cc1dc7a3Sopenharmony_ci        nameMux = {
159cc1dc7a3Sopenharmony_ci            "LDR": {
160cc1dc7a3Sopenharmony_ci                "input": "png",
161cc1dc7a3Sopenharmony_ci                "comp": "astc"
162cc1dc7a3Sopenharmony_ci            },
163cc1dc7a3Sopenharmony_ci            "LDRS": {
164cc1dc7a3Sopenharmony_ci                "input": "png",
165cc1dc7a3Sopenharmony_ci                "comp": "astc"
166cc1dc7a3Sopenharmony_ci            },
167cc1dc7a3Sopenharmony_ci            "HDR": {
168cc1dc7a3Sopenharmony_ci                "input": "exr",
169cc1dc7a3Sopenharmony_ci                "comp": "astc"
170cc1dc7a3Sopenharmony_ci            }
171cc1dc7a3Sopenharmony_ci        }
172cc1dc7a3Sopenharmony_ci
173cc1dc7a3Sopenharmony_ci        assert profile in nameMux.keys()
174cc1dc7a3Sopenharmony_ci        assert mode in nameMux["LDR"].keys()
175cc1dc7a3Sopenharmony_ci
176cc1dc7a3Sopenharmony_ci        scriptDir = os.path.dirname(__file__)
177cc1dc7a3Sopenharmony_ci        fileName = "%s-%s-1x1.%s" % (profile, image, nameMux[profile][mode])
178cc1dc7a3Sopenharmony_ci        return os.path.join(scriptDir, "Data", fileName)
179cc1dc7a3Sopenharmony_ci
180cc1dc7a3Sopenharmony_ci    def get_tmp_image_path(self, profile, mode):
181cc1dc7a3Sopenharmony_ci        """
182cc1dc7a3Sopenharmony_ci        Get the path of a temporary output image on disk.
183cc1dc7a3Sopenharmony_ci
184cc1dc7a3Sopenharmony_ci        Temporary files are automatically cleaned up when the test tearDown
185cc1dc7a3Sopenharmony_ci        occurs.
186cc1dc7a3Sopenharmony_ci
187cc1dc7a3Sopenharmony_ci        Args:
188cc1dc7a3Sopenharmony_ci            profile (str): The color profile. "EXP" means explicit which means
189cc1dc7a3Sopenharmony_ci                the "mode" parameter is interpreted as a literal file
190cc1dc7a3Sopenharmony_ci                extension not a symbolic mode.
191cc1dc7a3Sopenharmony_ci            mode (str): The type of image to load.
192cc1dc7a3Sopenharmony_ci
193cc1dc7a3Sopenharmony_ci        Returns:
194cc1dc7a3Sopenharmony_ci            str: The path to the test image file on disk.
195cc1dc7a3Sopenharmony_ci        """
196cc1dc7a3Sopenharmony_ci        # Handle explicit mode
197cc1dc7a3Sopenharmony_ci        if profile == "EXP":
198cc1dc7a3Sopenharmony_ci            tmpFile, tmpPath = tempfile.mkstemp(mode, dir=self.tempDir.name)
199cc1dc7a3Sopenharmony_ci            os.close(tmpFile)
200cc1dc7a3Sopenharmony_ci            os.remove(tmpPath)
201cc1dc7a3Sopenharmony_ci            return tmpPath
202cc1dc7a3Sopenharmony_ci
203cc1dc7a3Sopenharmony_ci        # Handle symbolic modes
204cc1dc7a3Sopenharmony_ci        nameMux = {
205cc1dc7a3Sopenharmony_ci            "LDR": {
206cc1dc7a3Sopenharmony_ci                "comp": ".astc",
207cc1dc7a3Sopenharmony_ci                "decomp": ".png",
208cc1dc7a3Sopenharmony_ci                "bad": ".foo"
209cc1dc7a3Sopenharmony_ci            },
210cc1dc7a3Sopenharmony_ci            "LDRS": {
211cc1dc7a3Sopenharmony_ci                "comp": ".astc",
212cc1dc7a3Sopenharmony_ci                "decomp": ".png",
213cc1dc7a3Sopenharmony_ci                "bad": ".foo"
214cc1dc7a3Sopenharmony_ci            },
215cc1dc7a3Sopenharmony_ci            "HDR": {
216cc1dc7a3Sopenharmony_ci                "comp": ".astc",
217cc1dc7a3Sopenharmony_ci                "decomp": ".exr",
218cc1dc7a3Sopenharmony_ci                "bad": ".foo"
219cc1dc7a3Sopenharmony_ci            }
220cc1dc7a3Sopenharmony_ci        }
221cc1dc7a3Sopenharmony_ci
222cc1dc7a3Sopenharmony_ci        assert profile in nameMux.keys()
223cc1dc7a3Sopenharmony_ci        assert mode in nameMux["LDR"].keys()
224cc1dc7a3Sopenharmony_ci
225cc1dc7a3Sopenharmony_ci        suffix = nameMux[profile][mode]
226cc1dc7a3Sopenharmony_ci        tmpFile, tmpPath = tempfile.mkstemp(suffix, dir=self.tempDir.name)
227cc1dc7a3Sopenharmony_ci        os.close(tmpFile)
228cc1dc7a3Sopenharmony_ci        os.remove(tmpPath)
229cc1dc7a3Sopenharmony_ci        return tmpPath
230cc1dc7a3Sopenharmony_ci
231cc1dc7a3Sopenharmony_ci
232cc1dc7a3Sopenharmony_ciclass CLIPTest(CLITestBase):
233cc1dc7a3Sopenharmony_ci    """
234cc1dc7a3Sopenharmony_ci    Command line interface positive tests.
235cc1dc7a3Sopenharmony_ci
236cc1dc7a3Sopenharmony_ci    These tests are designed to test the command line is handled correctly.
237cc1dc7a3Sopenharmony_ci    They are not detailed tests of the codec itself; only basic sanity checks
238cc1dc7a3Sopenharmony_ci    that some type of processing occurred are used.
239cc1dc7a3Sopenharmony_ci    """
240cc1dc7a3Sopenharmony_ci
241cc1dc7a3Sopenharmony_ci    def compare(self, image1, image2):
242cc1dc7a3Sopenharmony_ci        """
243cc1dc7a3Sopenharmony_ci        Utility function to compare two images.
244cc1dc7a3Sopenharmony_ci
245cc1dc7a3Sopenharmony_ci        Note that this comparison tests only decoded color values; any file
246cc1dc7a3Sopenharmony_ci        metadata is ignored, and encoding methods are not compared.
247cc1dc7a3Sopenharmony_ci
248cc1dc7a3Sopenharmony_ci        Args:
249cc1dc7a3Sopenharmony_ci            image1 (str): Path to the first image.
250cc1dc7a3Sopenharmony_ci            image2 (str): Path to the second image.
251cc1dc7a3Sopenharmony_ci
252cc1dc7a3Sopenharmony_ci        Returns:
253cc1dc7a3Sopenharmony_ci            bool: ``True` if the images are the same, ``False`` otherwise.
254cc1dc7a3Sopenharmony_ci        """
255cc1dc7a3Sopenharmony_ci        img1 = Image.open(image1)
256cc1dc7a3Sopenharmony_ci        img2 = Image.open(image2)
257cc1dc7a3Sopenharmony_ci
258cc1dc7a3Sopenharmony_ci        # Images must have same size
259cc1dc7a3Sopenharmony_ci        if img1.size != img2.size:
260cc1dc7a3Sopenharmony_ci            print("Size")
261cc1dc7a3Sopenharmony_ci            return False
262cc1dc7a3Sopenharmony_ci
263cc1dc7a3Sopenharmony_ci        # Images must have same number of color channels
264cc1dc7a3Sopenharmony_ci        if img1.getbands() != img2.getbands():
265cc1dc7a3Sopenharmony_ci            # ... unless the only different is alpha
266cc1dc7a3Sopenharmony_ci            self.assertEqual(img1.getbands(), ("R", "G", "B"))
267cc1dc7a3Sopenharmony_ci            self.assertEqual(img2.getbands(), ("R", "G", "B", "A"))
268cc1dc7a3Sopenharmony_ci
269cc1dc7a3Sopenharmony_ci            # ... and the alpha is always one
270cc1dc7a3Sopenharmony_ci            bands = img2.split()
271cc1dc7a3Sopenharmony_ci            alphaHist = bands[3].histogram()
272cc1dc7a3Sopenharmony_ci            self.assertEqual(sum(alphaHist[:-1]), 0)
273cc1dc7a3Sopenharmony_ci
274cc1dc7a3Sopenharmony_ci            # Generate a version of img2 without alpha
275cc1dc7a3Sopenharmony_ci            img2 = Image.merge("RGB", (bands[0], bands[1], bands[2]))
276cc1dc7a3Sopenharmony_ci
277cc1dc7a3Sopenharmony_ci        # Compute sum of absolute differences
278cc1dc7a3Sopenharmony_ci        dat1 = numpy.array(img1)
279cc1dc7a3Sopenharmony_ci        dat2 = numpy.array(img2)
280cc1dc7a3Sopenharmony_ci        sad = numpy.sum(numpy.abs(dat1 - dat2))
281cc1dc7a3Sopenharmony_ci
282cc1dc7a3Sopenharmony_ci        if sad != 0:
283cc1dc7a3Sopenharmony_ci            print(img1.load()[0, 0])
284cc1dc7a3Sopenharmony_ci            print(img2.load()[0, 0])
285cc1dc7a3Sopenharmony_ci
286cc1dc7a3Sopenharmony_ci        return sad == 0
287cc1dc7a3Sopenharmony_ci
288cc1dc7a3Sopenharmony_ci    def get_channel_rmse(self, image1, image2):
289cc1dc7a3Sopenharmony_ci        """
290cc1dc7a3Sopenharmony_ci        Get the channel-by-channel root mean square error.
291cc1dc7a3Sopenharmony_ci
292cc1dc7a3Sopenharmony_ci        Args:
293cc1dc7a3Sopenharmony_ci            image1 (str): Path to the first image.
294cc1dc7a3Sopenharmony_ci            image2 (str): Path to the second image.
295cc1dc7a3Sopenharmony_ci
296cc1dc7a3Sopenharmony_ci        Returns:
297cc1dc7a3Sopenharmony_ci            tuple: Tuple of floats containing the RMSE per channel.
298cc1dc7a3Sopenharmony_ci            None: Images could not be compared because they are different size.
299cc1dc7a3Sopenharmony_ci        """
300cc1dc7a3Sopenharmony_ci        img1 = Image.open(image1)
301cc1dc7a3Sopenharmony_ci        img2 = Image.open(image2)
302cc1dc7a3Sopenharmony_ci
303cc1dc7a3Sopenharmony_ci        # Images must have same size
304cc1dc7a3Sopenharmony_ci        if img1.size != img2.size:
305cc1dc7a3Sopenharmony_ci            return None
306cc1dc7a3Sopenharmony_ci
307cc1dc7a3Sopenharmony_ci        # Images must have same number of color channels
308cc1dc7a3Sopenharmony_ci        if img1.getbands() != img2.getbands():
309cc1dc7a3Sopenharmony_ci            # ... unless the only different is alpha
310cc1dc7a3Sopenharmony_ci            self.assertEqual(img1.getbands(), ("R", "G", "B"))
311cc1dc7a3Sopenharmony_ci            self.assertEqual(img2.getbands(), ("R", "G", "B", "A"))
312cc1dc7a3Sopenharmony_ci
313cc1dc7a3Sopenharmony_ci            # ... and the alpha is always one
314cc1dc7a3Sopenharmony_ci            bands = img2.split()
315cc1dc7a3Sopenharmony_ci            alphaHist = bands[3].histogram()
316cc1dc7a3Sopenharmony_ci            self.assertEqual(sum(alphaHist[:-1]), 0)
317cc1dc7a3Sopenharmony_ci
318cc1dc7a3Sopenharmony_ci            # Generate a version of img2 without alpha
319cc1dc7a3Sopenharmony_ci            img2 = Image.merge("RGB", (bands[0], bands[1], bands[2]))
320cc1dc7a3Sopenharmony_ci
321cc1dc7a3Sopenharmony_ci        # Compute root mean square error
322cc1dc7a3Sopenharmony_ci        img1bands = img1.split()
323cc1dc7a3Sopenharmony_ci        img2bands = img2.split()
324cc1dc7a3Sopenharmony_ci
325cc1dc7a3Sopenharmony_ci        rmseVals = []
326cc1dc7a3Sopenharmony_ci        imgBands = zip(img1bands, img2bands)
327cc1dc7a3Sopenharmony_ci        for img1Ch, img2Ch in imgBands:
328cc1dc7a3Sopenharmony_ci            imSz = numpy.prod(img1Ch.size)
329cc1dc7a3Sopenharmony_ci            dat1 = numpy.array(img1Ch)
330cc1dc7a3Sopenharmony_ci            dat2 = numpy.array(img2Ch)
331cc1dc7a3Sopenharmony_ci
332cc1dc7a3Sopenharmony_ci            sad = numpy.sum(numpy.square(dat1 - dat2))
333cc1dc7a3Sopenharmony_ci            mse = numpy.divide(sad, imSz)
334cc1dc7a3Sopenharmony_ci            rmse = numpy.sqrt(mse)
335cc1dc7a3Sopenharmony_ci            rmseVals.append(rmse)
336cc1dc7a3Sopenharmony_ci
337cc1dc7a3Sopenharmony_ci        return rmseVals
338cc1dc7a3Sopenharmony_ci
339cc1dc7a3Sopenharmony_ci    @staticmethod
340cc1dc7a3Sopenharmony_ci    def get_color_refs(mode, corners):
341cc1dc7a3Sopenharmony_ci        """
342cc1dc7a3Sopenharmony_ci        Build a set of reference colors from apriori color list.
343cc1dc7a3Sopenharmony_ci
344cc1dc7a3Sopenharmony_ci        Args:
345cc1dc7a3Sopenharmony_ci            mode (str): The color mode (LDR, or HDR)
346cc1dc7a3Sopenharmony_ci            corners (str or list): The corner or list of corners -- named TL,
347cc1dc7a3Sopenharmony_ci                TR, BL, and BR -- to return.
348cc1dc7a3Sopenharmony_ci
349cc1dc7a3Sopenharmony_ci        Returns:
350cc1dc7a3Sopenharmony_ci            tuple: The color value, if corners was a name.
351cc1dc7a3Sopenharmony_ci            [tuple]: List of color values, if corners was a list of names.
352cc1dc7a3Sopenharmony_ci        """
353cc1dc7a3Sopenharmony_ci        modes = {
354cc1dc7a3Sopenharmony_ci            "LDR": ASTCENC_TEST_PATTERN_LDR,
355cc1dc7a3Sopenharmony_ci            "HDR": ASTCENC_TEST_PATTERN_HDR
356cc1dc7a3Sopenharmony_ci        }
357cc1dc7a3Sopenharmony_ci
358cc1dc7a3Sopenharmony_ci        if isinstance(corners, str):
359cc1dc7a3Sopenharmony_ci            return [modes[mode][corners]]
360cc1dc7a3Sopenharmony_ci
361cc1dc7a3Sopenharmony_ci        return [modes[mode][corner] for corner in corners]
362cc1dc7a3Sopenharmony_ci
363cc1dc7a3Sopenharmony_ci    def assertColorSame(self, colorRef, colorNew, threshold=0.02, swiz=None):
364cc1dc7a3Sopenharmony_ci        """
365cc1dc7a3Sopenharmony_ci        Test if a color is the similar to a reference.
366cc1dc7a3Sopenharmony_ci
367cc1dc7a3Sopenharmony_ci        Will trigger a test failure if the colors are not within threshold.
368cc1dc7a3Sopenharmony_ci
369cc1dc7a3Sopenharmony_ci        Args:
370cc1dc7a3Sopenharmony_ci            colorRef (tuple): The reference color to compare with.
371cc1dc7a3Sopenharmony_ci            colorNew (tuple): The new color.
372cc1dc7a3Sopenharmony_ci            threshold (float): The allowed deviation from colorRef (ratio).
373cc1dc7a3Sopenharmony_ci            swiz (str): The swizzle string (4 characters from the set
374cc1dc7a3Sopenharmony_ci                `rgba01`), applied to the reference color.
375cc1dc7a3Sopenharmony_ci        """
376cc1dc7a3Sopenharmony_ci        self.assertEqual(len(colorRef), len(colorNew))
377cc1dc7a3Sopenharmony_ci
378cc1dc7a3Sopenharmony_ci        # Swizzle the reference color if needed
379cc1dc7a3Sopenharmony_ci        if swiz:
380cc1dc7a3Sopenharmony_ci            self.assertEqual(len(swiz), len(colorRef))
381cc1dc7a3Sopenharmony_ci
382cc1dc7a3Sopenharmony_ci            remap = {
383cc1dc7a3Sopenharmony_ci                "0": len(colorRef),
384cc1dc7a3Sopenharmony_ci                "1": len(colorRef) + 1
385cc1dc7a3Sopenharmony_ci            }
386cc1dc7a3Sopenharmony_ci
387cc1dc7a3Sopenharmony_ci            if len(colorRef) >= 1:
388cc1dc7a3Sopenharmony_ci                remap["r"] = 0
389cc1dc7a3Sopenharmony_ci            if len(colorRef) >= 2:
390cc1dc7a3Sopenharmony_ci                remap["g"] = 1
391cc1dc7a3Sopenharmony_ci            if len(colorRef) >= 3:
392cc1dc7a3Sopenharmony_ci                remap["b"] = 2
393cc1dc7a3Sopenharmony_ci            if len(colorRef) >= 4:
394cc1dc7a3Sopenharmony_ci                remap["a"] = 3
395cc1dc7a3Sopenharmony_ci
396cc1dc7a3Sopenharmony_ci            colorRefExt = list(colorRef) + [0.0, 1.0]
397cc1dc7a3Sopenharmony_ci            colorRef = [colorRefExt[remap[s]] for s in swiz]
398cc1dc7a3Sopenharmony_ci
399cc1dc7a3Sopenharmony_ci        for chRef, chNew in zip(colorRef, colorNew):
400cc1dc7a3Sopenharmony_ci            deltaMax = chRef * threshold
401cc1dc7a3Sopenharmony_ci            self.assertAlmostEqual(chRef, chNew, delta=deltaMax)
402cc1dc7a3Sopenharmony_ci
403cc1dc7a3Sopenharmony_ci    def exec(self, command, pattern=None):
404cc1dc7a3Sopenharmony_ci        """
405cc1dc7a3Sopenharmony_ci        Execute a positive test.
406cc1dc7a3Sopenharmony_ci
407cc1dc7a3Sopenharmony_ci        Will trigger a test failure if the subprocess return code is any value
408cc1dc7a3Sopenharmony_ci        other than zero.
409cc1dc7a3Sopenharmony_ci
410cc1dc7a3Sopenharmony_ci        Args:
411cc1dc7a3Sopenharmony_ci            command (list(str)): The command to execute.
412cc1dc7a3Sopenharmony_ci            pattern (re.Pattern): The regex pattern to search for, must
413cc1dc7a3Sopenharmony_ci                contain a single group (this is returned to the caller). The
414cc1dc7a3Sopenharmony_ci                test will fail if no pattern match is found.
415cc1dc7a3Sopenharmony_ci
416cc1dc7a3Sopenharmony_ci        Returns:
417cc1dc7a3Sopenharmony_ci            str: The stdout output of the child process, or the first group
418cc1dc7a3Sopenharmony_ci               from the passed regex pattern.
419cc1dc7a3Sopenharmony_ci        """
420cc1dc7a3Sopenharmony_ci        try:
421cc1dc7a3Sopenharmony_ci            result = sp.run(command, stdout=sp.PIPE, stderr=sp.PIPE,
422cc1dc7a3Sopenharmony_ci                            universal_newlines=True, check=True)
423cc1dc7a3Sopenharmony_ci            error = False
424cc1dc7a3Sopenharmony_ci        except sp.CalledProcessError as ex:
425cc1dc7a3Sopenharmony_ci            result = ex
426cc1dc7a3Sopenharmony_ci            error = True
427cc1dc7a3Sopenharmony_ci
428cc1dc7a3Sopenharmony_ci        # Emit debug logging if needed
429cc1dc7a3Sopenharmony_ci        if ASTCENC_CLI_ALWAYS or (error and ASTCENC_CLI_ON_ERROR):
430cc1dc7a3Sopenharmony_ci            # Format for shell replay
431cc1dc7a3Sopenharmony_ci            print("\n" + " ".join(command))
432cc1dc7a3Sopenharmony_ci            # Format for script command list replay
433cc1dc7a3Sopenharmony_ci            print("\n" + ", ".join(("\"%s\"" % x for x in command)))
434cc1dc7a3Sopenharmony_ci
435cc1dc7a3Sopenharmony_ci        if ASTCENC_LOG_ALWAYS or (error and ASTCENC_LOG_ON_ERROR):
436cc1dc7a3Sopenharmony_ci            print(result.stdout)
437cc1dc7a3Sopenharmony_ci
438cc1dc7a3Sopenharmony_ci        rcode = result.returncode
439cc1dc7a3Sopenharmony_ci
440cc1dc7a3Sopenharmony_ci        if rcode < 0:
441cc1dc7a3Sopenharmony_ci            msg = "Exec died with signal %s" % signal.Signals(-rcode).name
442cc1dc7a3Sopenharmony_ci            self.assertGreaterEqual(rcode, 0, msg)
443cc1dc7a3Sopenharmony_ci
444cc1dc7a3Sopenharmony_ci        if rcode > 0:
445cc1dc7a3Sopenharmony_ci            msg = "Exec died with application error %u" % rcode
446cc1dc7a3Sopenharmony_ci            self.assertEqual(rcode, 0, msg)
447cc1dc7a3Sopenharmony_ci
448cc1dc7a3Sopenharmony_ci        # If there is a regex pattern provided, then search for it
449cc1dc7a3Sopenharmony_ci        if pattern:
450cc1dc7a3Sopenharmony_ci            match = pattern.search(result.stdout)
451cc1dc7a3Sopenharmony_ci            self.assertIsNotNone(match)
452cc1dc7a3Sopenharmony_ci            return match.group(1)
453cc1dc7a3Sopenharmony_ci
454cc1dc7a3Sopenharmony_ci        return result.stdout
455cc1dc7a3Sopenharmony_ci
456cc1dc7a3Sopenharmony_ci    def test_ldr_compress(self):
457cc1dc7a3Sopenharmony_ci        """
458cc1dc7a3Sopenharmony_ci        Test basic LDR compression.
459cc1dc7a3Sopenharmony_ci        """
460cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDR", "input", "A")
461cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDR", "comp")
462cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("LDR", "comp", "A")
463cc1dc7a3Sopenharmony_ci
464cc1dc7a3Sopenharmony_ci        command = [self.binary, "-cl", imIn, imOut, "6x6", "-exhaustive"]
465cc1dc7a3Sopenharmony_ci        self.exec(command)
466cc1dc7a3Sopenharmony_ci        self.assertTrue(filecmp.cmp(imRef, imOut, False))
467cc1dc7a3Sopenharmony_ci
468cc1dc7a3Sopenharmony_ci    def test_srgb_compress(self):
469cc1dc7a3Sopenharmony_ci        """
470cc1dc7a3Sopenharmony_ci        Test basic LDR sRGB compression.
471cc1dc7a3Sopenharmony_ci        """
472cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDRS", "input", "A")
473cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDRS", "comp")
474cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("LDRS", "comp", "A")
475cc1dc7a3Sopenharmony_ci
476cc1dc7a3Sopenharmony_ci        command = [self.binary, "-cs", imIn, imOut, "6x6", "-exhaustive"]
477cc1dc7a3Sopenharmony_ci        self.exec(command)
478cc1dc7a3Sopenharmony_ci        self.assertTrue(filecmp.cmp(imRef, imOut, False))
479cc1dc7a3Sopenharmony_ci
480cc1dc7a3Sopenharmony_ci    def test_hdr_compress1(self):
481cc1dc7a3Sopenharmony_ci        """
482cc1dc7a3Sopenharmony_ci        Test basic HDR + LDR alpha compression.
483cc1dc7a3Sopenharmony_ci        """
484cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("HDR", "input", "A")
485cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("HDR", "comp")
486cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("HDR", "comp", "A")
487cc1dc7a3Sopenharmony_ci
488cc1dc7a3Sopenharmony_ci        command = [self.binary, "-ch", imIn, imOut, "6x6", "-exhaustive"]
489cc1dc7a3Sopenharmony_ci        self.exec(command)
490cc1dc7a3Sopenharmony_ci        self.assertTrue(filecmp.cmp(imRef, imOut, False))
491cc1dc7a3Sopenharmony_ci
492cc1dc7a3Sopenharmony_ci    def test_hdr_compress2(self):
493cc1dc7a3Sopenharmony_ci        """
494cc1dc7a3Sopenharmony_ci        Test basic HDR + HDR alpha compression.
495cc1dc7a3Sopenharmony_ci        """
496cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("HDR", "input", "A")
497cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("HDR", "comp")
498cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("HDR", "comp", "A")
499cc1dc7a3Sopenharmony_ci
500cc1dc7a3Sopenharmony_ci        command = [self.binary, "-cH", imIn, imOut, "6x6", "-exhaustive"]
501cc1dc7a3Sopenharmony_ci        self.exec(command)
502cc1dc7a3Sopenharmony_ci        self.assertTrue(filecmp.cmp(imRef, imOut, False))
503cc1dc7a3Sopenharmony_ci
504cc1dc7a3Sopenharmony_ci    def test_ldr_decompress(self):
505cc1dc7a3Sopenharmony_ci        """
506cc1dc7a3Sopenharmony_ci        Test basic LDR decompression.
507cc1dc7a3Sopenharmony_ci        """
508cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDR", "comp", "A")
509cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDR", "decomp")
510cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("LDR", "input", "A")
511cc1dc7a3Sopenharmony_ci
512cc1dc7a3Sopenharmony_ci        command = [self.binary, "-dl", imIn, imOut]
513cc1dc7a3Sopenharmony_ci        self.exec(command)
514cc1dc7a3Sopenharmony_ci        self.assertTrue(self.compare(imRef, imOut))
515cc1dc7a3Sopenharmony_ci
516cc1dc7a3Sopenharmony_ci    def test_srgb_decompress(self):
517cc1dc7a3Sopenharmony_ci        """
518cc1dc7a3Sopenharmony_ci        Test basic LDR sRGB decompression.
519cc1dc7a3Sopenharmony_ci        """
520cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDRS", "comp", "A")
521cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDRS", "decomp")
522cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("LDRS", "input", "A")
523cc1dc7a3Sopenharmony_ci
524cc1dc7a3Sopenharmony_ci        command = [self.binary, "-ds", imIn, imOut]
525cc1dc7a3Sopenharmony_ci        self.exec(command)
526cc1dc7a3Sopenharmony_ci        self.assertTrue(self.compare(imRef, imOut))
527cc1dc7a3Sopenharmony_ci
528cc1dc7a3Sopenharmony_ci    def test_hdr_decompress1(self):
529cc1dc7a3Sopenharmony_ci        """
530cc1dc7a3Sopenharmony_ci        Test basic HDR + LDR alpha decompression.
531cc1dc7a3Sopenharmony_ci        """
532cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("HDR", "comp", "A")
533cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("HDR", "decomp")
534cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("HDR", "input", "A")
535cc1dc7a3Sopenharmony_ci
536cc1dc7a3Sopenharmony_ci        command = [self.binary, "-dh", imIn, imOut]
537cc1dc7a3Sopenharmony_ci        self.exec(command)
538cc1dc7a3Sopenharmony_ci
539cc1dc7a3Sopenharmony_ci        colRef = tli.Image(imRef).get_colors((0, 0))
540cc1dc7a3Sopenharmony_ci        colOut = tli.Image(imOut).get_colors((0, 0))
541cc1dc7a3Sopenharmony_ci        self.assertColorSame(colRef, colOut)
542cc1dc7a3Sopenharmony_ci
543cc1dc7a3Sopenharmony_ci    def test_hdr_decompress2(self):
544cc1dc7a3Sopenharmony_ci        """
545cc1dc7a3Sopenharmony_ci        Test basic HDR + HDR alpha decompression.
546cc1dc7a3Sopenharmony_ci        """
547cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("HDR", "comp", "A")
548cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("HDR", "decomp")
549cc1dc7a3Sopenharmony_ci        imRef = self.get_ref_image_path("HDR", "input", "A")
550cc1dc7a3Sopenharmony_ci
551cc1dc7a3Sopenharmony_ci        command = [self.binary, "-dH", imIn, imOut]
552cc1dc7a3Sopenharmony_ci        self.exec(command)
553cc1dc7a3Sopenharmony_ci
554cc1dc7a3Sopenharmony_ci        colRef = tli.Image(imRef).get_colors((0, 0))
555cc1dc7a3Sopenharmony_ci        colOut = tli.Image(imOut).get_colors((0, 0))
556cc1dc7a3Sopenharmony_ci        self.assertColorSame(colRef, colOut)
557cc1dc7a3Sopenharmony_ci
558cc1dc7a3Sopenharmony_ci    def test_ldr_roundtrip(self):
559cc1dc7a3Sopenharmony_ci        """
560cc1dc7a3Sopenharmony_ci        Test basic LDR round-trip
561cc1dc7a3Sopenharmony_ci        """
562cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDR", "input", "A")
563cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDR", "decomp")
564cc1dc7a3Sopenharmony_ci
565cc1dc7a3Sopenharmony_ci        command = [self.binary, "-tl", imIn, imOut, "6x6", "-exhaustive"]
566cc1dc7a3Sopenharmony_ci        self.exec(command)
567cc1dc7a3Sopenharmony_ci        self.assertTrue(self.compare(imIn, imOut))
568cc1dc7a3Sopenharmony_ci
569cc1dc7a3Sopenharmony_ci    def test_srgb_roundtrip(self):
570cc1dc7a3Sopenharmony_ci        """
571cc1dc7a3Sopenharmony_ci        Test basic LDR sRGB round-trip
572cc1dc7a3Sopenharmony_ci        """
573cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDRS", "input", "A")
574cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDRS", "decomp")
575cc1dc7a3Sopenharmony_ci
576cc1dc7a3Sopenharmony_ci        command = [self.binary, "-ts", imIn, imOut, "6x6", "-exhaustive"]
577cc1dc7a3Sopenharmony_ci        self.exec(command)
578cc1dc7a3Sopenharmony_ci        self.assertTrue(self.compare(imIn, imOut))
579cc1dc7a3Sopenharmony_ci
580cc1dc7a3Sopenharmony_ci    def test_hdr_roundtrip1(self):
581cc1dc7a3Sopenharmony_ci        """
582cc1dc7a3Sopenharmony_ci        Test basic HDR + LDR alpha round-trip.
583cc1dc7a3Sopenharmony_ci        """
584cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("HDR", "input", "A")
585cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("HDR", "decomp")
586cc1dc7a3Sopenharmony_ci
587cc1dc7a3Sopenharmony_ci        command = [self.binary, "-th", imIn, imOut, "6x6", "-exhaustive"]
588cc1dc7a3Sopenharmony_ci        self.exec(command)
589cc1dc7a3Sopenharmony_ci        colIn = tli.Image(imIn).get_colors((0, 0))
590cc1dc7a3Sopenharmony_ci        colOut = tli.Image(imOut).get_colors((0, 0))
591cc1dc7a3Sopenharmony_ci        self.assertColorSame(colIn, colOut)
592cc1dc7a3Sopenharmony_ci
593cc1dc7a3Sopenharmony_ci    def test_hdr_roundtrip2(self):
594cc1dc7a3Sopenharmony_ci        """
595cc1dc7a3Sopenharmony_ci        Test basic HDR + HDR alpha round-trip.
596cc1dc7a3Sopenharmony_ci        """
597cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("HDR", "input", "A")
598cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("HDR", "decomp")
599cc1dc7a3Sopenharmony_ci
600cc1dc7a3Sopenharmony_ci        command = [self.binary, "-tH", imIn, imOut, "6x6", "-exhaustive"]
601cc1dc7a3Sopenharmony_ci        self.exec(command)
602cc1dc7a3Sopenharmony_ci        colIn = tli.Image(imIn).get_colors((0, 0))
603cc1dc7a3Sopenharmony_ci        colOut = tli.Image(imOut).get_colors((0, 0))
604cc1dc7a3Sopenharmony_ci        self.assertColorSame(colIn, colOut)
605cc1dc7a3Sopenharmony_ci
606cc1dc7a3Sopenharmony_ci    def test_valid_2d_block_sizes(self):
607cc1dc7a3Sopenharmony_ci        """
608cc1dc7a3Sopenharmony_ci        Test all valid block sizes are accepted (2D images).
609cc1dc7a3Sopenharmony_ci        """
610cc1dc7a3Sopenharmony_ci        blockSizes = [
611cc1dc7a3Sopenharmony_ci            "4x4", "5x4", "5x5", "6x5", "6x6", "8x5", "8x6",
612cc1dc7a3Sopenharmony_ci            "10x5", "10x6", "8x8", "10x8", "10x10", "12x10", "12x12"
613cc1dc7a3Sopenharmony_ci        ]
614cc1dc7a3Sopenharmony_ci
615cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDR", "input", "A")
616cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDR", "decomp")
617cc1dc7a3Sopenharmony_ci
618cc1dc7a3Sopenharmony_ci        for blk in blockSizes:
619cc1dc7a3Sopenharmony_ci            with self.subTest(blockSize=blk):
620cc1dc7a3Sopenharmony_ci                command = [self.binary, "-tl", imIn, imOut, blk, "-exhaustive"]
621cc1dc7a3Sopenharmony_ci                self.exec(command)
622cc1dc7a3Sopenharmony_ci                colIn = tli.Image(imIn).get_colors((0, 0))
623cc1dc7a3Sopenharmony_ci                colOut = tli.Image(imOut).get_colors((0, 0))
624cc1dc7a3Sopenharmony_ci                self.assertColorSame(colIn, colOut)
625cc1dc7a3Sopenharmony_ci
626cc1dc7a3Sopenharmony_ci    def test_valid_3d_block_sizes(self):
627cc1dc7a3Sopenharmony_ci        """
628cc1dc7a3Sopenharmony_ci        Test all valid block sizes are accepted (3D images).
629cc1dc7a3Sopenharmony_ci        """
630cc1dc7a3Sopenharmony_ci        blockSizes = [
631cc1dc7a3Sopenharmony_ci            "3x3x3",
632cc1dc7a3Sopenharmony_ci            "4x3x3", "4x4x3", "4x4x4",
633cc1dc7a3Sopenharmony_ci            "5x4x4", "5x5x4", "5x5x5",
634cc1dc7a3Sopenharmony_ci            "6x5x5", "6x6x5", "6x6x6"
635cc1dc7a3Sopenharmony_ci        ]
636cc1dc7a3Sopenharmony_ci
637cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDR", "input", "A")
638cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDR", "decomp")
639cc1dc7a3Sopenharmony_ci
640cc1dc7a3Sopenharmony_ci        for blk in blockSizes:
641cc1dc7a3Sopenharmony_ci            with self.subTest(blockSize=blk):
642cc1dc7a3Sopenharmony_ci                command = [self.binary, "-tl", imIn, imOut, blk, "-exhaustive"]
643cc1dc7a3Sopenharmony_ci                self.exec(command)
644cc1dc7a3Sopenharmony_ci                colIn = tli.Image(imIn).get_colors((0, 0))
645cc1dc7a3Sopenharmony_ci                colOut = tli.Image(imOut).get_colors((0, 0))
646cc1dc7a3Sopenharmony_ci                self.assertColorSame(colIn, colOut)
647cc1dc7a3Sopenharmony_ci
648cc1dc7a3Sopenharmony_ci    def test_valid_presets(self):
649cc1dc7a3Sopenharmony_ci        """
650cc1dc7a3Sopenharmony_ci        Test all valid presets are accepted
651cc1dc7a3Sopenharmony_ci        """
652cc1dc7a3Sopenharmony_ci        presets = ["-fastest", "-fast", "-medium",
653cc1dc7a3Sopenharmony_ci                   "-thorough", "-verythorough", "-exhaustive"]
654cc1dc7a3Sopenharmony_ci
655cc1dc7a3Sopenharmony_ci        imIn = self.get_ref_image_path("LDR", "input", "A")
656cc1dc7a3Sopenharmony_ci        imOut = self.get_tmp_image_path("LDR", "decomp")
657cc1dc7a3Sopenharmony_ci
658cc1dc7a3Sopenharmony_ci        for preset in presets:
659cc1dc7a3Sopenharmony_ci            with self.subTest(preset=preset):
660cc1dc7a3Sopenharmony_ci                command = [self.binary, "-tl", imIn, imOut, "4x4", preset]
661cc1dc7a3Sopenharmony_ci                self.exec(command)
662cc1dc7a3Sopenharmony_ci                colIn = tli.Image(imIn).get_colors((0, 0))
663cc1dc7a3Sopenharmony_ci                colOut = tli.Image(imOut).get_colors((0, 0))
664cc1dc7a3Sopenharmony_ci                self.assertColorSame(colIn, colOut)
665cc1dc7a3Sopenharmony_ci
666cc1dc7a3Sopenharmony_ci    def test_valid_ldr_input_formats(self):
667cc1dc7a3Sopenharmony_ci        """
668cc1dc7a3Sopenharmony_ci        Test valid LDR input file formats.
669cc1dc7a3Sopenharmony_ci        """
670cc1dc7a3Sopenharmony_ci        imgFormats = ["bmp", "dds", "jpg", "ktx", "png", "tga"]
671cc1dc7a3Sopenharmony_ci
672cc1dc7a3Sopenharmony_ci        for imgFormat in imgFormats:
673cc1dc7a3Sopenharmony_ci            with self.subTest(imgFormat=imgFormat):
674cc1dc7a3Sopenharmony_ci                imIn = "./Test/Data/Tiles/ldr.%s" % imgFormat
675cc1dc7a3Sopenharmony_ci                imOut = self.get_tmp_image_path("LDR", "decomp")
676cc1dc7a3Sopenharmony_ci
677cc1dc7a3Sopenharmony_ci                command = [self.binary, "-tl", imIn, imOut, "4x4", "-fast"]
678cc1dc7a3Sopenharmony_ci                self.exec(command)
679cc1dc7a3Sopenharmony_ci
680cc1dc7a3Sopenharmony_ci                # Check colors if image wrapper supports it
681cc1dc7a3Sopenharmony_ci                if tli.Image.is_format_supported(imgFormat):
682cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
683cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut).get_colors((7, 7))
684cc1dc7a3Sopenharmony_ci
685cc1dc7a3Sopenharmony_ci                    # Catch exception and add fallback for tga handling
686cc1dc7a3Sopenharmony_ci                    # having unstable origin in ImageMagick
687cc1dc7a3Sopenharmony_ci                    try:
688cc1dc7a3Sopenharmony_ci                        self.assertColorSame(colIn, colOut)
689cc1dc7a3Sopenharmony_ci                        continue
690cc1dc7a3Sopenharmony_ci                    except AssertionError as ex:
691cc1dc7a3Sopenharmony_ci                        if imgFormat != "tga":
692cc1dc7a3Sopenharmony_ci                            raise ex
693cc1dc7a3Sopenharmony_ci
694cc1dc7a3Sopenharmony_ci                    # Try yflipped TGA image
695cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
696cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut).get_colors((7, 1))
697cc1dc7a3Sopenharmony_ci                    self.assertColorSame(colIn, colOut)
698cc1dc7a3Sopenharmony_ci
699cc1dc7a3Sopenharmony_ci    def test_valid_uncomp_ldr_output_formats(self):
700cc1dc7a3Sopenharmony_ci        """
701cc1dc7a3Sopenharmony_ci        Test valid uncompressed LDR output file formats.
702cc1dc7a3Sopenharmony_ci        """
703cc1dc7a3Sopenharmony_ci        imgFormats = ["bmp", "dds", "ktx", "png", "tga"]
704cc1dc7a3Sopenharmony_ci
705cc1dc7a3Sopenharmony_ci        for imgFormat in imgFormats:
706cc1dc7a3Sopenharmony_ci            with self.subTest(imgFormat=imgFormat):
707cc1dc7a3Sopenharmony_ci                imIn = self.get_ref_image_path("LDR", "input", "A")
708cc1dc7a3Sopenharmony_ci                imOut = self.get_tmp_image_path("EXP", ".%s" % imgFormat)
709cc1dc7a3Sopenharmony_ci
710cc1dc7a3Sopenharmony_ci                command = [self.binary, "-tl", imIn, imOut, "4x4", "-fast"]
711cc1dc7a3Sopenharmony_ci                self.exec(command)
712cc1dc7a3Sopenharmony_ci
713cc1dc7a3Sopenharmony_ci                # Check colors if image wrapper supports it
714cc1dc7a3Sopenharmony_ci                if tli.Image.is_format_supported(imgFormat):
715cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
716cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut).get_colors((7, 7))
717cc1dc7a3Sopenharmony_ci                    self.assertColorSame(colIn, colOut)
718cc1dc7a3Sopenharmony_ci
719cc1dc7a3Sopenharmony_ci    def test_valid_comp_ldr_output_formats(self):
720cc1dc7a3Sopenharmony_ci        """
721cc1dc7a3Sopenharmony_ci        Test valid compressed LDR output file formats.
722cc1dc7a3Sopenharmony_ci        """
723cc1dc7a3Sopenharmony_ci        imgFormats = ["astc", "ktx"]
724cc1dc7a3Sopenharmony_ci
725cc1dc7a3Sopenharmony_ci        for imgFormat in imgFormats:
726cc1dc7a3Sopenharmony_ci            with self.subTest(imgFormat=imgFormat):
727cc1dc7a3Sopenharmony_ci                imIn = self.get_ref_image_path("LDR", "input", "A")
728cc1dc7a3Sopenharmony_ci                imOut = self.get_tmp_image_path("EXP", ".%s" % imgFormat)
729cc1dc7a3Sopenharmony_ci                imOut2 = self.get_tmp_image_path("LDR", "decomp")
730cc1dc7a3Sopenharmony_ci
731cc1dc7a3Sopenharmony_ci                command = [self.binary, "-cl", imIn, imOut, "4x4", "-fast"]
732cc1dc7a3Sopenharmony_ci                self.exec(command)
733cc1dc7a3Sopenharmony_ci
734cc1dc7a3Sopenharmony_ci                command = [self.binary, "-dl", imOut, imOut2]
735cc1dc7a3Sopenharmony_ci                self.exec(command)
736cc1dc7a3Sopenharmony_ci
737cc1dc7a3Sopenharmony_ci                # Check colors if image wrapper supports it
738cc1dc7a3Sopenharmony_ci                if tli.Image.is_format_supported(imgFormat):
739cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
740cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut2).get_colors((7, 7))
741cc1dc7a3Sopenharmony_ci                    self.assertColorSame(colIn, colOut2)
742cc1dc7a3Sopenharmony_ci
743cc1dc7a3Sopenharmony_ci    def test_valid_hdr_input_formats(self):
744cc1dc7a3Sopenharmony_ci        """
745cc1dc7a3Sopenharmony_ci        Test valid HDR input file formats.
746cc1dc7a3Sopenharmony_ci        """
747cc1dc7a3Sopenharmony_ci        imgFormats = ["exr", "hdr"]
748cc1dc7a3Sopenharmony_ci
749cc1dc7a3Sopenharmony_ci        for imgFormat in imgFormats:
750cc1dc7a3Sopenharmony_ci            with self.subTest(imgFormat=imgFormat):
751cc1dc7a3Sopenharmony_ci                imIn = "./Test/Data/Tiles/hdr.%s" % imgFormat
752cc1dc7a3Sopenharmony_ci                imOut = self.get_tmp_image_path("HDR", "decomp")
753cc1dc7a3Sopenharmony_ci
754cc1dc7a3Sopenharmony_ci                command = [self.binary, "-th", imIn, imOut, "4x4", "-fast"]
755cc1dc7a3Sopenharmony_ci                self.exec(command)
756cc1dc7a3Sopenharmony_ci
757cc1dc7a3Sopenharmony_ci                # Check colors if image wrapper supports it
758cc1dc7a3Sopenharmony_ci                if tli.Image.is_format_supported(imgFormat, profile="hdr"):
759cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
760cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut).get_colors((7, 7))
761cc1dc7a3Sopenharmony_ci                    self.assertColorSame(colIn, colOut)
762cc1dc7a3Sopenharmony_ci
763cc1dc7a3Sopenharmony_ci    def test_valid_uncomp_hdr_output_formats(self):
764cc1dc7a3Sopenharmony_ci        """
765cc1dc7a3Sopenharmony_ci        Test valid uncompressed HDR output file formats.
766cc1dc7a3Sopenharmony_ci        """
767cc1dc7a3Sopenharmony_ci        imgFormats = ["dds", "exr", "hdr", "ktx"]
768cc1dc7a3Sopenharmony_ci
769cc1dc7a3Sopenharmony_ci        for imgFormat in imgFormats:
770cc1dc7a3Sopenharmony_ci            with self.subTest(imgFormat=imgFormat):
771cc1dc7a3Sopenharmony_ci                imIn = self.get_ref_image_path("HDR", "input", "A")
772cc1dc7a3Sopenharmony_ci                imOut = self.get_tmp_image_path("EXP", ".%s" % imgFormat)
773cc1dc7a3Sopenharmony_ci
774cc1dc7a3Sopenharmony_ci                command = [self.binary, "-th", imIn, imOut, "4x4", "-fast"]
775cc1dc7a3Sopenharmony_ci                self.exec(command)
776cc1dc7a3Sopenharmony_ci
777cc1dc7a3Sopenharmony_ci                # Check colors if image wrapper supports it
778cc1dc7a3Sopenharmony_ci                if tli.Image.is_format_supported(imgFormat, profile="hdr"):
779cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
780cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut).get_colors((7, 7))
781cc1dc7a3Sopenharmony_ci                    self.assertColorSame(colIn, colOut)
782cc1dc7a3Sopenharmony_ci
783cc1dc7a3Sopenharmony_ci    def test_valid_comp_hdr_output_formats(self):
784cc1dc7a3Sopenharmony_ci        """
785cc1dc7a3Sopenharmony_ci        Test valid compressed HDR output file formats.
786cc1dc7a3Sopenharmony_ci        """
787cc1dc7a3Sopenharmony_ci        imgFormats = ["astc", "ktx"]
788cc1dc7a3Sopenharmony_ci
789cc1dc7a3Sopenharmony_ci        for imgFormat in imgFormats:
790cc1dc7a3Sopenharmony_ci            with self.subTest(imgFormat=imgFormat):
791cc1dc7a3Sopenharmony_ci                imIn = self.get_ref_image_path("HDR", "input", "A")
792cc1dc7a3Sopenharmony_ci                imOut = self.get_tmp_image_path("EXP", ".%s" % imgFormat)
793cc1dc7a3Sopenharmony_ci                imOut2 = self.get_tmp_image_path("HDR", "decomp")
794cc1dc7a3Sopenharmony_ci
795cc1dc7a3Sopenharmony_ci                command = [self.binary, "-ch", imIn, imOut, "4x4", "-fast"]
796cc1dc7a3Sopenharmony_ci                self.exec(command)
797cc1dc7a3Sopenharmony_ci
798cc1dc7a3Sopenharmony_ci                command = [self.binary, "-dh", imOut, imOut2]
799cc1dc7a3Sopenharmony_ci                self.exec(command)
800cc1dc7a3Sopenharmony_ci
801cc1dc7a3Sopenharmony_ci                # Check colors if image wrapper supports it
802cc1dc7a3Sopenharmony_ci                if tli.Image.is_format_supported(imgFormat):
803cc1dc7a3Sopenharmony_ci                    colIn = tli.Image(imIn).get_colors((7, 7))
804cc1dc7a3Sopenharmony_ci                    colOut = tli.Image(imOut2).get_colors((7, 7))
805cc1dc7a3Sopenharmony_ci                    self.assertColorSame(colIn, colOut2)
806cc1dc7a3Sopenharmony_ci
807cc1dc7a3Sopenharmony_ci    def test_compress_normal_psnr(self):
808cc1dc7a3Sopenharmony_ci        """
809cc1dc7a3Sopenharmony_ci        Test compression of normal textures using PSNR error metrics.
810cc1dc7a3Sopenharmony_ci        """
811cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
812cc1dc7a3Sopenharmony_ci
813cc1dc7a3Sopenharmony_ci        command = [
814cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
815cc1dc7a3Sopenharmony_ci            "./Test/Images/Small/LDR-XY/ldr-xy-00.png",
816cc1dc7a3Sopenharmony_ci            decompFile, "5x5", "-exhaustive"]
817cc1dc7a3Sopenharmony_ci
818cc1dc7a3Sopenharmony_ci        refdB = float(self.exec(command, LDR_RGB_PSNR_PATTERN))
819cc1dc7a3Sopenharmony_ci
820cc1dc7a3Sopenharmony_ci        command.append("-normal")
821cc1dc7a3Sopenharmony_ci        testdB = float(self.exec(command, LDR_RGB_PSNR_PATTERN))
822cc1dc7a3Sopenharmony_ci
823cc1dc7a3Sopenharmony_ci        # Note that this test simply asserts that the "-normal_psnr" is
824cc1dc7a3Sopenharmony_ci        # connected and affects the output. We don't test it does something
825cc1dc7a3Sopenharmony_ci        # useful; that it outside the scope of this test case.
826cc1dc7a3Sopenharmony_ci        self.assertNotEqual(refdB, testdB)
827cc1dc7a3Sopenharmony_ci
828cc1dc7a3Sopenharmony_ci    def test_compress_normal_percep(self):
829cc1dc7a3Sopenharmony_ci        """
830cc1dc7a3Sopenharmony_ci        Test compression of normal textures using perceptual error metrics.
831cc1dc7a3Sopenharmony_ci        """
832cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
833cc1dc7a3Sopenharmony_ci
834cc1dc7a3Sopenharmony_ci        command = [
835cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
836cc1dc7a3Sopenharmony_ci            "./Test/Images/Small/LDR-XY/ldr-xy-00.png",
837cc1dc7a3Sopenharmony_ci            decompFile, "4x4", "-exhaustive"]
838cc1dc7a3Sopenharmony_ci
839cc1dc7a3Sopenharmony_ci        refdB = float(self.exec(command, LDR_RGB_PSNR_PATTERN))
840cc1dc7a3Sopenharmony_ci
841cc1dc7a3Sopenharmony_ci        command.append("-normal")
842cc1dc7a3Sopenharmony_ci        command.append("-perceptual")
843cc1dc7a3Sopenharmony_ci        testdB = float(self.exec(command, LDR_RGB_PSNR_PATTERN))
844cc1dc7a3Sopenharmony_ci
845cc1dc7a3Sopenharmony_ci        # Note that this test simply asserts that the "-normal -percep" is
846cc1dc7a3Sopenharmony_ci        # connected and affects the output. We don't test it does something
847cc1dc7a3Sopenharmony_ci        # useful; that it outside the scope of this test case.
848cc1dc7a3Sopenharmony_ci        self.assertNotEqual(refdB, testdB)
849cc1dc7a3Sopenharmony_ci
850cc1dc7a3Sopenharmony_ci    def test_compress_esw(self):
851cc1dc7a3Sopenharmony_ci        """
852cc1dc7a3Sopenharmony_ci        Test compression swizzles.
853cc1dc7a3Sopenharmony_ci        """
854cc1dc7a3Sopenharmony_ci        # The swizzles to test
855cc1dc7a3Sopenharmony_ci        swizzles = ["rgba", "g0r1", "rrrg"]
856cc1dc7a3Sopenharmony_ci
857cc1dc7a3Sopenharmony_ci        # Compress a swizzled image
858cc1dc7a3Sopenharmony_ci        for swizzle in swizzles:
859cc1dc7a3Sopenharmony_ci            with self.subTest(swizzle=swizzle):
860cc1dc7a3Sopenharmony_ci                decompFile = self.get_tmp_image_path("LDR", "decomp")
861cc1dc7a3Sopenharmony_ci
862cc1dc7a3Sopenharmony_ci                command = [
863cc1dc7a3Sopenharmony_ci                    self.binary, "-tl",
864cc1dc7a3Sopenharmony_ci                    "./Test/Data/Tiles/ldr.png",
865cc1dc7a3Sopenharmony_ci                    decompFile, "4x4", "-exhaustive",
866cc1dc7a3Sopenharmony_ci                    "-esw", swizzle]
867cc1dc7a3Sopenharmony_ci
868cc1dc7a3Sopenharmony_ci                self.exec(command)
869cc1dc7a3Sopenharmony_ci
870cc1dc7a3Sopenharmony_ci                # Fetch the three color
871cc1dc7a3Sopenharmony_ci                img = tli.Image(decompFile)
872cc1dc7a3Sopenharmony_ci                colorVal = img.get_colors([(7, 7)])
873cc1dc7a3Sopenharmony_ci                colorRef = self.get_color_refs("LDR", "BR")
874cc1dc7a3Sopenharmony_ci                self.assertColorSame(colorRef[0], colorVal[0], swiz=swizzle)
875cc1dc7a3Sopenharmony_ci
876cc1dc7a3Sopenharmony_ci    def test_compress_dsw(self):
877cc1dc7a3Sopenharmony_ci        """
878cc1dc7a3Sopenharmony_ci        Test decompression swizzles.
879cc1dc7a3Sopenharmony_ci        """
880cc1dc7a3Sopenharmony_ci        # The swizzles to test
881cc1dc7a3Sopenharmony_ci        swizzles = ["rgba", "g0r1", "rrrg"]
882cc1dc7a3Sopenharmony_ci
883cc1dc7a3Sopenharmony_ci        # Decompress a swizzled image
884cc1dc7a3Sopenharmony_ci        for swizzle in swizzles:
885cc1dc7a3Sopenharmony_ci            with self.subTest(swizzle=swizzle):
886cc1dc7a3Sopenharmony_ci                decompFile = self.get_tmp_image_path("LDR", "decomp")
887cc1dc7a3Sopenharmony_ci
888cc1dc7a3Sopenharmony_ci                command = [
889cc1dc7a3Sopenharmony_ci                    self.binary, "-tl",
890cc1dc7a3Sopenharmony_ci                    "./Test/Data/Tiles/ldr.png",
891cc1dc7a3Sopenharmony_ci                    decompFile, "4x4", "-exhaustive",
892cc1dc7a3Sopenharmony_ci                    "-dsw", swizzle]
893cc1dc7a3Sopenharmony_ci
894cc1dc7a3Sopenharmony_ci                self.exec(command)
895cc1dc7a3Sopenharmony_ci
896cc1dc7a3Sopenharmony_ci                # Fetch the three color
897cc1dc7a3Sopenharmony_ci                img = tli.Image(decompFile)
898cc1dc7a3Sopenharmony_ci                colorVal = img.get_colors([(7, 7)])
899cc1dc7a3Sopenharmony_ci                colorRef = self.get_color_refs("LDR", "BR")
900cc1dc7a3Sopenharmony_ci                self.assertColorSame(colorRef[0], colorVal[0], swiz=swizzle)
901cc1dc7a3Sopenharmony_ci
902cc1dc7a3Sopenharmony_ci    def test_compress_esw_dsw(self):
903cc1dc7a3Sopenharmony_ci        """
904cc1dc7a3Sopenharmony_ci        Test compression and decompression swizzles
905cc1dc7a3Sopenharmony_ci        """
906cc1dc7a3Sopenharmony_ci        # Compress a swizzled image, and swizzle back in decompression
907cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
908cc1dc7a3Sopenharmony_ci
909cc1dc7a3Sopenharmony_ci        command = [
910cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
911cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
912cc1dc7a3Sopenharmony_ci            decompFile, "4x4", "-exhaustive",
913cc1dc7a3Sopenharmony_ci            "-esw", "gbar", "-dsw", "argb"]
914cc1dc7a3Sopenharmony_ci
915cc1dc7a3Sopenharmony_ci        self.exec(command)
916cc1dc7a3Sopenharmony_ci
917cc1dc7a3Sopenharmony_ci        # Fetch the three color
918cc1dc7a3Sopenharmony_ci        img = tli.Image(decompFile)
919cc1dc7a3Sopenharmony_ci        colorVal = img.get_colors([(7, 7)])
920cc1dc7a3Sopenharmony_ci        colorRef = self.get_color_refs("LDR", "BR")
921cc1dc7a3Sopenharmony_ci        self.assertColorSame(colorRef[0], colorVal[0])
922cc1dc7a3Sopenharmony_ci
923cc1dc7a3Sopenharmony_ci    def test_compress_flip(self):
924cc1dc7a3Sopenharmony_ci        """
925cc1dc7a3Sopenharmony_ci        Test LDR image flip on compression.
926cc1dc7a3Sopenharmony_ci        """
927cc1dc7a3Sopenharmony_ci        # Compress a flipped image
928cc1dc7a3Sopenharmony_ci        compFile = self.get_tmp_image_path("LDR", "comp")
929cc1dc7a3Sopenharmony_ci
930cc1dc7a3Sopenharmony_ci        command = [
931cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
932cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
933cc1dc7a3Sopenharmony_ci            compFile, "4x4", "-fast", "-yflip"]
934cc1dc7a3Sopenharmony_ci
935cc1dc7a3Sopenharmony_ci        self.exec(command)
936cc1dc7a3Sopenharmony_ci
937cc1dc7a3Sopenharmony_ci        # Decompress a non-flipped image
938cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
939cc1dc7a3Sopenharmony_ci
940cc1dc7a3Sopenharmony_ci        command = [
941cc1dc7a3Sopenharmony_ci            self.binary, "-dl",
942cc1dc7a3Sopenharmony_ci            compFile,
943cc1dc7a3Sopenharmony_ci            decompFile]
944cc1dc7a3Sopenharmony_ci
945cc1dc7a3Sopenharmony_ci        self.exec(command)
946cc1dc7a3Sopenharmony_ci
947cc1dc7a3Sopenharmony_ci        # Compare TL (0, 0) with BL - should match
948cc1dc7a3Sopenharmony_ci        colorRef = self.get_color_refs("LDR", "BL")
949cc1dc7a3Sopenharmony_ci
950cc1dc7a3Sopenharmony_ci        img = tli.Image(decompFile)
951cc1dc7a3Sopenharmony_ci        colorVal = img.get_colors([(0, 0)])
952cc1dc7a3Sopenharmony_ci        self.assertColorSame(colorRef[0], colorVal[0])
953cc1dc7a3Sopenharmony_ci
954cc1dc7a3Sopenharmony_ci    def test_decompress_flip(self):
955cc1dc7a3Sopenharmony_ci        """
956cc1dc7a3Sopenharmony_ci        Test LDR image flip on decompression.
957cc1dc7a3Sopenharmony_ci        """
958cc1dc7a3Sopenharmony_ci        # Compress a non-flipped image
959cc1dc7a3Sopenharmony_ci        compFile = self.get_tmp_image_path("LDR", "comp")
960cc1dc7a3Sopenharmony_ci
961cc1dc7a3Sopenharmony_ci        command = [
962cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
963cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
964cc1dc7a3Sopenharmony_ci            compFile, "4x4", "-fast"]
965cc1dc7a3Sopenharmony_ci
966cc1dc7a3Sopenharmony_ci        self.exec(command)
967cc1dc7a3Sopenharmony_ci
968cc1dc7a3Sopenharmony_ci        # Decompress a flipped image
969cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
970cc1dc7a3Sopenharmony_ci
971cc1dc7a3Sopenharmony_ci        command = [
972cc1dc7a3Sopenharmony_ci            self.binary, "-dl",
973cc1dc7a3Sopenharmony_ci            compFile,
974cc1dc7a3Sopenharmony_ci            decompFile, "-yflip"]
975cc1dc7a3Sopenharmony_ci
976cc1dc7a3Sopenharmony_ci        self.exec(command)
977cc1dc7a3Sopenharmony_ci
978cc1dc7a3Sopenharmony_ci        # Compare TL (0, 0) with BL - should match
979cc1dc7a3Sopenharmony_ci        colorRef = self.get_color_refs("LDR", "BL")
980cc1dc7a3Sopenharmony_ci
981cc1dc7a3Sopenharmony_ci        img = tli.Image(decompFile)
982cc1dc7a3Sopenharmony_ci        colorVal = img.get_colors([(0, 0)])
983cc1dc7a3Sopenharmony_ci        self.assertColorSame(colorRef[0], colorVal[0])
984cc1dc7a3Sopenharmony_ci
985cc1dc7a3Sopenharmony_ci    def test_roundtrip_flip(self):
986cc1dc7a3Sopenharmony_ci        """
987cc1dc7a3Sopenharmony_ci        Test LDR image flip on roundtrip (no flip should occur).
988cc1dc7a3Sopenharmony_ci        """
989cc1dc7a3Sopenharmony_ci        # Compress and decompressed a flipped LDR image
990cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
991cc1dc7a3Sopenharmony_ci
992cc1dc7a3Sopenharmony_ci        command = [
993cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
994cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
995cc1dc7a3Sopenharmony_ci            decompFile, "4x4", "-fast", "-yflip"]
996cc1dc7a3Sopenharmony_ci
997cc1dc7a3Sopenharmony_ci        self.exec(command)
998cc1dc7a3Sopenharmony_ci
999cc1dc7a3Sopenharmony_ci        # Compare TL (0, 0) with TL - should match - i.e. no flip
1000cc1dc7a3Sopenharmony_ci        colorRef = self.get_color_refs("LDR", "TL")
1001cc1dc7a3Sopenharmony_ci
1002cc1dc7a3Sopenharmony_ci        img = tli.Image(decompFile)
1003cc1dc7a3Sopenharmony_ci        colorVal = img.get_colors([(0, 0)])
1004cc1dc7a3Sopenharmony_ci
1005cc1dc7a3Sopenharmony_ci        self.assertColorSame(colorRef[0], colorVal[0])
1006cc1dc7a3Sopenharmony_ci
1007cc1dc7a3Sopenharmony_ci    def test_channel_weighting(self):
1008cc1dc7a3Sopenharmony_ci        """
1009cc1dc7a3Sopenharmony_ci        Test channel weighting.
1010cc1dc7a3Sopenharmony_ci        """
1011cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1012cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1013cc1dc7a3Sopenharmony_ci
1014cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1015cc1dc7a3Sopenharmony_ci        command = [
1016cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1017cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1018cc1dc7a3Sopenharmony_ci
1019cc1dc7a3Sopenharmony_ci        self.exec(command)
1020cc1dc7a3Sopenharmony_ci        baseRMSE = self.get_channel_rmse(inputFile, decompFile)
1021cc1dc7a3Sopenharmony_ci
1022cc1dc7a3Sopenharmony_ci        # Note: Using -cw can result in a worse result than not using -cw,
1023cc1dc7a3Sopenharmony_ci        # with regressions in RMSE for the high-weighted channel. This is
1024cc1dc7a3Sopenharmony_ci        # particularly an issue in synthetic images, as they are more likely to
1025cc1dc7a3Sopenharmony_ci        # hit corner cases in the heuristics. It happens to "work" for the
1026cc1dc7a3Sopenharmony_ci        # selected test image and these settings, but might start to fail in
1027cc1dc7a3Sopenharmony_ci        # future due to compressor changes.
1028cc1dc7a3Sopenharmony_ci
1029cc1dc7a3Sopenharmony_ci        # Test each channel with a high weight
1030cc1dc7a3Sopenharmony_ci        for chIdx, chName in ((0, "R"), (1, "G"), (2, "B"), (3, "A")):
1031cc1dc7a3Sopenharmony_ci            with self.subTest(channel=chName):
1032cc1dc7a3Sopenharmony_ci                cwArg = ["%s" % (10 if x == chIdx else 1) for x in range(0, 4)]
1033cc1dc7a3Sopenharmony_ci                command2 = command + ["-cw"] + cwArg
1034cc1dc7a3Sopenharmony_ci                self.exec(command2)
1035cc1dc7a3Sopenharmony_ci                chRMSE = self.get_channel_rmse(inputFile, decompFile)
1036cc1dc7a3Sopenharmony_ci                self.assertLess(chRMSE[chIdx], baseRMSE[chIdx])
1037cc1dc7a3Sopenharmony_ci
1038cc1dc7a3Sopenharmony_ci    def test_partition_count_limit(self):
1039cc1dc7a3Sopenharmony_ci        """
1040cc1dc7a3Sopenharmony_ci        Test partition count limit.
1041cc1dc7a3Sopenharmony_ci        """
1042cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1043cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1044cc1dc7a3Sopenharmony_ci
1045cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1046cc1dc7a3Sopenharmony_ci        command = [
1047cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1048cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1049cc1dc7a3Sopenharmony_ci
1050cc1dc7a3Sopenharmony_ci        self.exec(command)
1051cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1052cc1dc7a3Sopenharmony_ci
1053cc1dc7a3Sopenharmony_ci        command += ["-partitioncountlimit", "1"]
1054cc1dc7a3Sopenharmony_ci        self.exec(command)
1055cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1056cc1dc7a3Sopenharmony_ci
1057cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1058cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1059cc1dc7a3Sopenharmony_ci
1060cc1dc7a3Sopenharmony_ci    def test_2partition_index_limit(self):
1061cc1dc7a3Sopenharmony_ci        """
1062cc1dc7a3Sopenharmony_ci        Test partition index limit.
1063cc1dc7a3Sopenharmony_ci        """
1064cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1065cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1066cc1dc7a3Sopenharmony_ci
1067cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1068cc1dc7a3Sopenharmony_ci        command = [
1069cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1070cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1071cc1dc7a3Sopenharmony_ci
1072cc1dc7a3Sopenharmony_ci        self.exec(command)
1073cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1074cc1dc7a3Sopenharmony_ci
1075cc1dc7a3Sopenharmony_ci        command += ["-2partitionindexlimit", "1"]
1076cc1dc7a3Sopenharmony_ci        self.exec(command)
1077cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1078cc1dc7a3Sopenharmony_ci
1079cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1080cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1081cc1dc7a3Sopenharmony_ci
1082cc1dc7a3Sopenharmony_ci    def test_3partition_index_limit(self):
1083cc1dc7a3Sopenharmony_ci        """
1084cc1dc7a3Sopenharmony_ci        Test partition index limit.
1085cc1dc7a3Sopenharmony_ci        """
1086cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1087cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1088cc1dc7a3Sopenharmony_ci
1089cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1090cc1dc7a3Sopenharmony_ci        command = [
1091cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1092cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1093cc1dc7a3Sopenharmony_ci
1094cc1dc7a3Sopenharmony_ci        self.exec(command)
1095cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1096cc1dc7a3Sopenharmony_ci
1097cc1dc7a3Sopenharmony_ci        command += ["-3partitionindexlimit", "1"]
1098cc1dc7a3Sopenharmony_ci        self.exec(command)
1099cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1100cc1dc7a3Sopenharmony_ci
1101cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1102cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1103cc1dc7a3Sopenharmony_ci
1104cc1dc7a3Sopenharmony_ci    def test_4partition_index_limit(self):
1105cc1dc7a3Sopenharmony_ci        """
1106cc1dc7a3Sopenharmony_ci        Test partition index limit.
1107cc1dc7a3Sopenharmony_ci        """
1108cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1109cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1110cc1dc7a3Sopenharmony_ci
1111cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1112cc1dc7a3Sopenharmony_ci        command = [
1113cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1114cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1115cc1dc7a3Sopenharmony_ci
1116cc1dc7a3Sopenharmony_ci        self.exec(command)
1117cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1118cc1dc7a3Sopenharmony_ci
1119cc1dc7a3Sopenharmony_ci        command += ["-4partitionindexlimit", "1"]
1120cc1dc7a3Sopenharmony_ci        self.exec(command)
1121cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1122cc1dc7a3Sopenharmony_ci
1123cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1124cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1125cc1dc7a3Sopenharmony_ci
1126cc1dc7a3Sopenharmony_ci    def test_blockmode_limit(self):
1127cc1dc7a3Sopenharmony_ci        """
1128cc1dc7a3Sopenharmony_ci        Test block mode limit.
1129cc1dc7a3Sopenharmony_ci        """
1130cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1131cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1132cc1dc7a3Sopenharmony_ci
1133cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1134cc1dc7a3Sopenharmony_ci        command = [
1135cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1136cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1137cc1dc7a3Sopenharmony_ci
1138cc1dc7a3Sopenharmony_ci        self.exec(command)
1139cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1140cc1dc7a3Sopenharmony_ci
1141cc1dc7a3Sopenharmony_ci        command += ["-blockmodelimit", "25"]
1142cc1dc7a3Sopenharmony_ci        self.exec(command)
1143cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1144cc1dc7a3Sopenharmony_ci
1145cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1146cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1147cc1dc7a3Sopenharmony_ci
1148cc1dc7a3Sopenharmony_ci    def test_refinement_limit(self):
1149cc1dc7a3Sopenharmony_ci        """
1150cc1dc7a3Sopenharmony_ci        Test refinement limit.
1151cc1dc7a3Sopenharmony_ci        """
1152cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1153cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1154cc1dc7a3Sopenharmony_ci
1155cc1dc7a3Sopenharmony_ci        command = [
1156cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1157cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1158cc1dc7a3Sopenharmony_ci
1159cc1dc7a3Sopenharmony_ci        self.exec(command)
1160cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1161cc1dc7a3Sopenharmony_ci
1162cc1dc7a3Sopenharmony_ci        command += ["-refinementlimit", "1"]
1163cc1dc7a3Sopenharmony_ci        self.exec(command)
1164cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1165cc1dc7a3Sopenharmony_ci
1166cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1167cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1168cc1dc7a3Sopenharmony_ci
1169cc1dc7a3Sopenharmony_ci    def test_candidate_limit(self):
1170cc1dc7a3Sopenharmony_ci        """
1171cc1dc7a3Sopenharmony_ci        Test candidate limit.
1172cc1dc7a3Sopenharmony_ci        """
1173cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1174cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1175cc1dc7a3Sopenharmony_ci
1176cc1dc7a3Sopenharmony_ci        command = [
1177cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1178cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1179cc1dc7a3Sopenharmony_ci
1180cc1dc7a3Sopenharmony_ci        self.exec(command)
1181cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1182cc1dc7a3Sopenharmony_ci
1183cc1dc7a3Sopenharmony_ci        command += ["-candidatelimit", "1"]
1184cc1dc7a3Sopenharmony_ci        self.exec(command)
1185cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1186cc1dc7a3Sopenharmony_ci
1187cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1188cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1189cc1dc7a3Sopenharmony_ci
1190cc1dc7a3Sopenharmony_ci    def test_db_cutoff_limit(self):
1191cc1dc7a3Sopenharmony_ci        """
1192cc1dc7a3Sopenharmony_ci        Test db cutoff limit.
1193cc1dc7a3Sopenharmony_ci        """
1194cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1195cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1196cc1dc7a3Sopenharmony_ci
1197cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1198cc1dc7a3Sopenharmony_ci        command = [
1199cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1200cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1201cc1dc7a3Sopenharmony_ci
1202cc1dc7a3Sopenharmony_ci        self.exec(command)
1203cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1204cc1dc7a3Sopenharmony_ci
1205cc1dc7a3Sopenharmony_ci        command += ["-dblimit", "10"]
1206cc1dc7a3Sopenharmony_ci        self.exec(command)
1207cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1208cc1dc7a3Sopenharmony_ci
1209cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce cutoff quality
1210cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1211cc1dc7a3Sopenharmony_ci
1212cc1dc7a3Sopenharmony_ci    def test_2partition_early_limit(self):
1213cc1dc7a3Sopenharmony_ci        """
1214cc1dc7a3Sopenharmony_ci        Test 2 partition early limit.
1215cc1dc7a3Sopenharmony_ci        """
1216cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1217cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1218cc1dc7a3Sopenharmony_ci
1219cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1220cc1dc7a3Sopenharmony_ci        command = [
1221cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1222cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1223cc1dc7a3Sopenharmony_ci
1224cc1dc7a3Sopenharmony_ci        self.exec(command)
1225cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1226cc1dc7a3Sopenharmony_ci
1227cc1dc7a3Sopenharmony_ci        command += ["-2partitionlimitfactor", "1.0"]
1228cc1dc7a3Sopenharmony_ci        self.exec(command)
1229cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1230cc1dc7a3Sopenharmony_ci
1231cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1232cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1233cc1dc7a3Sopenharmony_ci
1234cc1dc7a3Sopenharmony_ci    def test_3partition_early_limit(self):
1235cc1dc7a3Sopenharmony_ci        """
1236cc1dc7a3Sopenharmony_ci        Test 3 partition early limit.
1237cc1dc7a3Sopenharmony_ci        """
1238cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1239cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1240cc1dc7a3Sopenharmony_ci
1241cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1242cc1dc7a3Sopenharmony_ci        command = [
1243cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1244cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1245cc1dc7a3Sopenharmony_ci
1246cc1dc7a3Sopenharmony_ci        self.exec(command)
1247cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1248cc1dc7a3Sopenharmony_ci
1249cc1dc7a3Sopenharmony_ci        command += ["-3partitionlimitfactor", "1.0"]
1250cc1dc7a3Sopenharmony_ci        self.exec(command)
1251cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1252cc1dc7a3Sopenharmony_ci
1253cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1254cc1dc7a3Sopenharmony_ci        self.assertNotEqual(testRMSE, refRMSE)
1255cc1dc7a3Sopenharmony_ci
1256cc1dc7a3Sopenharmony_ci    def test_2plane_correlation_limit(self):
1257cc1dc7a3Sopenharmony_ci        """
1258cc1dc7a3Sopenharmony_ci        Test 2 plane correlation limit.
1259cc1dc7a3Sopenharmony_ci        """
1260cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1261cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1262cc1dc7a3Sopenharmony_ci
1263cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1264cc1dc7a3Sopenharmony_ci        command = [
1265cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1266cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1267cc1dc7a3Sopenharmony_ci
1268cc1dc7a3Sopenharmony_ci        self.exec(command)
1269cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1270cc1dc7a3Sopenharmony_ci
1271cc1dc7a3Sopenharmony_ci        command += ["-2planelimitcorrelation", "0.1"]
1272cc1dc7a3Sopenharmony_ci        self.exec(command)
1273cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1274cc1dc7a3Sopenharmony_ci
1275cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1276cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1277cc1dc7a3Sopenharmony_ci
1278cc1dc7a3Sopenharmony_ci    def test_2partition_candidate_limit(self):
1279cc1dc7a3Sopenharmony_ci        """
1280cc1dc7a3Sopenharmony_ci        Test 2 partition partitioning candidate limit.
1281cc1dc7a3Sopenharmony_ci        """
1282cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1283cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1284cc1dc7a3Sopenharmony_ci
1285cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1286cc1dc7a3Sopenharmony_ci        command = [
1287cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1288cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1289cc1dc7a3Sopenharmony_ci
1290cc1dc7a3Sopenharmony_ci        self.exec(command)
1291cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1292cc1dc7a3Sopenharmony_ci
1293cc1dc7a3Sopenharmony_ci        command += ["-2partitioncandidatelimit", "1"]
1294cc1dc7a3Sopenharmony_ci        self.exec(command)
1295cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1296cc1dc7a3Sopenharmony_ci
1297cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1298cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1299cc1dc7a3Sopenharmony_ci
1300cc1dc7a3Sopenharmony_ci    def test_3partition_candidate_limit(self):
1301cc1dc7a3Sopenharmony_ci        """
1302cc1dc7a3Sopenharmony_ci        Test 3 partition partitioning candidate limit.
1303cc1dc7a3Sopenharmony_ci        """
1304cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1305cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1306cc1dc7a3Sopenharmony_ci
1307cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1308cc1dc7a3Sopenharmony_ci        command = [
1309cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1310cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1311cc1dc7a3Sopenharmony_ci
1312cc1dc7a3Sopenharmony_ci        self.exec(command)
1313cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1314cc1dc7a3Sopenharmony_ci
1315cc1dc7a3Sopenharmony_ci        command += ["-3partitioncandidatelimit", "1"]
1316cc1dc7a3Sopenharmony_ci        self.exec(command)
1317cc1dc7a3Sopenharmony_ci        testRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1318cc1dc7a3Sopenharmony_ci
1319cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1320cc1dc7a3Sopenharmony_ci        self.assertGreater(testRMSE, refRMSE)
1321cc1dc7a3Sopenharmony_ci
1322cc1dc7a3Sopenharmony_ci    def test_4partition_candidate_limit(self):
1323cc1dc7a3Sopenharmony_ci        """
1324cc1dc7a3Sopenharmony_ci        Test 4 partition partitioning candidate limit.
1325cc1dc7a3Sopenharmony_ci        """
1326cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1327cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1328cc1dc7a3Sopenharmony_ci
1329cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1330cc1dc7a3Sopenharmony_ci        command = [
1331cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1332cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1333cc1dc7a3Sopenharmony_ci
1334cc1dc7a3Sopenharmony_ci        self.exec(command)
1335cc1dc7a3Sopenharmony_ci        refRMSE = sum(self.get_channel_rmse(inputFile, decompFile))
1336cc1dc7a3Sopenharmony_ci
1337cc1dc7a3Sopenharmony_ci        command += ["-4partitioncandidatelimit", "1"]
1338cc1dc7a3Sopenharmony_ci        self.exec(command)
1339cc1dc7a3Sopenharmony_ci
1340cc1dc7a3Sopenharmony_ci        # RMSE should get worse (higher) if we reduce search space
1341cc1dc7a3Sopenharmony_ci        # Don't check this here, as 4 partitions not used in any Small image
1342cc1dc7a3Sopenharmony_ci        # even for -exhaustive, BUT command line option must be accepted and
1343cc1dc7a3Sopenharmony_ci        # not error ...
1344cc1dc7a3Sopenharmony_ci        # self.assertGreater(testRMSE, refRMSE)
1345cc1dc7a3Sopenharmony_ci
1346cc1dc7a3Sopenharmony_ci    @unittest.skipIf(os.cpu_count() == 1, "Cannot test on single core host")
1347cc1dc7a3Sopenharmony_ci    def test_thread_count(self):
1348cc1dc7a3Sopenharmony_ci        """
1349cc1dc7a3Sopenharmony_ci        Test codec thread count.
1350cc1dc7a3Sopenharmony_ci        """
1351cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1352cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1353cc1dc7a3Sopenharmony_ci
1354cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1355cc1dc7a3Sopenharmony_ci        command = [
1356cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1357cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1358cc1dc7a3Sopenharmony_ci
1359cc1dc7a3Sopenharmony_ci        start = time.time()
1360cc1dc7a3Sopenharmony_ci        self.exec(command)
1361cc1dc7a3Sopenharmony_ci        refTime = time.time() - start
1362cc1dc7a3Sopenharmony_ci
1363cc1dc7a3Sopenharmony_ci        command += ["-j", "1"]
1364cc1dc7a3Sopenharmony_ci        start = time.time()
1365cc1dc7a3Sopenharmony_ci        self.exec(command)
1366cc1dc7a3Sopenharmony_ci        testTime = time.time() - start
1367cc1dc7a3Sopenharmony_ci
1368cc1dc7a3Sopenharmony_ci        # Test time should get slower with fewer threads
1369cc1dc7a3Sopenharmony_ci        self.assertGreater(testTime, refTime)
1370cc1dc7a3Sopenharmony_ci
1371cc1dc7a3Sopenharmony_ci    def test_silent(self):
1372cc1dc7a3Sopenharmony_ci        """
1373cc1dc7a3Sopenharmony_ci        Test silent
1374cc1dc7a3Sopenharmony_ci        """
1375cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1376cc1dc7a3Sopenharmony_ci        decompFile = self.get_tmp_image_path("LDR", "decomp")
1377cc1dc7a3Sopenharmony_ci
1378cc1dc7a3Sopenharmony_ci        # Compute the basic image without any channel weights
1379cc1dc7a3Sopenharmony_ci        command = [
1380cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1381cc1dc7a3Sopenharmony_ci            inputFile, decompFile, "4x4", "-medium"]
1382cc1dc7a3Sopenharmony_ci        stdout = self.exec(command)
1383cc1dc7a3Sopenharmony_ci
1384cc1dc7a3Sopenharmony_ci        command += ["-silent"]
1385cc1dc7a3Sopenharmony_ci        stdoutSilent = self.exec(command)
1386cc1dc7a3Sopenharmony_ci
1387cc1dc7a3Sopenharmony_ci        # Check that stdout is shorter in silent mode. Note that this doesn't
1388cc1dc7a3Sopenharmony_ci        # check that it is as silent as it should be, just that silent is wired
1389cc1dc7a3Sopenharmony_ci        # somewhere ...
1390cc1dc7a3Sopenharmony_ci        self.assertLess(len(stdoutSilent), len(stdout))
1391cc1dc7a3Sopenharmony_ci
1392cc1dc7a3Sopenharmony_ci    def test_image_quality_stability(self):
1393cc1dc7a3Sopenharmony_ci        """
1394cc1dc7a3Sopenharmony_ci        Test that a round-trip and a file-based round-trip give same result.
1395cc1dc7a3Sopenharmony_ci        """
1396cc1dc7a3Sopenharmony_ci        inputFile = "./Test/Images/Small/LDR-RGBA/ldr-rgba-00.png"
1397cc1dc7a3Sopenharmony_ci        p1DecFile = self.get_tmp_image_path("LDR", "decomp")
1398cc1dc7a3Sopenharmony_ci        p2CompFile = self.get_tmp_image_path("LDR", "comp")
1399cc1dc7a3Sopenharmony_ci        p2DecFile = self.get_tmp_image_path("LDR", "decomp")
1400cc1dc7a3Sopenharmony_ci
1401cc1dc7a3Sopenharmony_ci        # Compute the first image using a direct round-trip
1402cc1dc7a3Sopenharmony_ci        command = [self.binary, "-tl", inputFile, p1DecFile, "4x4", "-medium"]
1403cc1dc7a3Sopenharmony_ci        self.exec(command)
1404cc1dc7a3Sopenharmony_ci
1405cc1dc7a3Sopenharmony_ci        # Compute the first image using a file-based round-trip
1406cc1dc7a3Sopenharmony_ci        command = [self.binary, "-cl", inputFile, p2CompFile, "4x4", "-medium",
1407cc1dc7a3Sopenharmony_ci                   "-decode_unorm8"]
1408cc1dc7a3Sopenharmony_ci        self.exec(command)
1409cc1dc7a3Sopenharmony_ci        command = [self.binary, "-dl", p2CompFile, p2DecFile]
1410cc1dc7a3Sopenharmony_ci        self.exec(command)
1411cc1dc7a3Sopenharmony_ci
1412cc1dc7a3Sopenharmony_ci        # RMSE should be the same
1413cc1dc7a3Sopenharmony_ci        p1RMSE = sum(self.get_channel_rmse(inputFile, p1DecFile))
1414cc1dc7a3Sopenharmony_ci        p2RMSE = sum(self.get_channel_rmse(inputFile, p2DecFile))
1415cc1dc7a3Sopenharmony_ci        self.assertEqual(p1RMSE, p2RMSE)
1416cc1dc7a3Sopenharmony_ci
1417cc1dc7a3Sopenharmony_ci
1418cc1dc7a3Sopenharmony_ciclass CLINTest(CLITestBase):
1419cc1dc7a3Sopenharmony_ci    """
1420cc1dc7a3Sopenharmony_ci    Command line interface negative tests.
1421cc1dc7a3Sopenharmony_ci
1422cc1dc7a3Sopenharmony_ci    These tests are designed to test that bad inputs to the command line are
1423cc1dc7a3Sopenharmony_ci    handled cleanly and that errors are correctly thrown.
1424cc1dc7a3Sopenharmony_ci
1425cc1dc7a3Sopenharmony_ci    Note that many tests are mutations of a valid positive test command line,
1426cc1dc7a3Sopenharmony_ci    to ensure that the base command line is valid before it is mutated many
1427cc1dc7a3Sopenharmony_ci    of these tests include a *positive test* to ensure that the starting point
1428cc1dc7a3Sopenharmony_ci    is actually a valid command line (otherwise we could be throwing an
1429cc1dc7a3Sopenharmony_ci    arbitrary error).
1430cc1dc7a3Sopenharmony_ci    """
1431cc1dc7a3Sopenharmony_ci
1432cc1dc7a3Sopenharmony_ci    def exec(self, command, expectPass=False):
1433cc1dc7a3Sopenharmony_ci        """
1434cc1dc7a3Sopenharmony_ci        Execute a negative test.
1435cc1dc7a3Sopenharmony_ci
1436cc1dc7a3Sopenharmony_ci        Test will automatically fail if:
1437cc1dc7a3Sopenharmony_ci
1438cc1dc7a3Sopenharmony_ci        * The subprocess return code is zero, unless ``expectPass==True``.
1439cc1dc7a3Sopenharmony_ci        * The subprocess correctly returned non-zero, but without any error
1440cc1dc7a3Sopenharmony_ci          message.
1441cc1dc7a3Sopenharmony_ci        * The subprocess dies with any kind of signal.
1442cc1dc7a3Sopenharmony_ci
1443cc1dc7a3Sopenharmony_ci        Args:
1444cc1dc7a3Sopenharmony_ci            command (list(str)): The command to execute.
1445cc1dc7a3Sopenharmony_ci            expectPass (bool): ``True`` if this command is actually expected to
1446cc1dc7a3Sopenharmony_ci                pass, which is used to validate commands before mutating them.
1447cc1dc7a3Sopenharmony_ci        """
1448cc1dc7a3Sopenharmony_ci        try:
1449cc1dc7a3Sopenharmony_ci            result = sp.run(command, stdout=sp.PIPE, stderr=sp.PIPE,
1450cc1dc7a3Sopenharmony_ci                            universal_newlines=True, check=True)
1451cc1dc7a3Sopenharmony_ci            error = False
1452cc1dc7a3Sopenharmony_ci        except sp.CalledProcessError as ex:
1453cc1dc7a3Sopenharmony_ci            # Pop out of the CPE scope to handle the error, as this reduces
1454cc1dc7a3Sopenharmony_ci            # test log verbosity on failure by avoiding nested exceptions
1455cc1dc7a3Sopenharmony_ci            result = ex
1456cc1dc7a3Sopenharmony_ci            error = True
1457cc1dc7a3Sopenharmony_ci
1458cc1dc7a3Sopenharmony_ci        rcode = result.returncode
1459cc1dc7a3Sopenharmony_ci
1460cc1dc7a3Sopenharmony_ci        # Emit debug logging if needed (negative rcode is a signal)
1461cc1dc7a3Sopenharmony_ci        badResult = (error == expectPass) or (rcode < 0)
1462cc1dc7a3Sopenharmony_ci
1463cc1dc7a3Sopenharmony_ci        if ASTCENC_CLI_ALWAYS or (badResult and ASTCENC_CLI_ON_ERROR_NEG):
1464cc1dc7a3Sopenharmony_ci            # Format for shell replay
1465cc1dc7a3Sopenharmony_ci            print("\n" + " ".join(command))
1466cc1dc7a3Sopenharmony_ci            # Format for script command list replay
1467cc1dc7a3Sopenharmony_ci            print("\n" + ", ".join(("\"%s\"" % x for x in command)))
1468cc1dc7a3Sopenharmony_ci
1469cc1dc7a3Sopenharmony_ci        if ASTCENC_LOG_ALWAYS or (badResult and ASTCENC_LOG_ON_ERROR_NEG):
1470cc1dc7a3Sopenharmony_ci            print(result.stdout)
1471cc1dc7a3Sopenharmony_ci
1472cc1dc7a3Sopenharmony_ci        # If we expected a pass, then rcode == 0
1473cc1dc7a3Sopenharmony_ci        if expectPass:
1474cc1dc7a3Sopenharmony_ci            self.assertEqual(rcode, 0, "Exec did not pass as expected")
1475cc1dc7a3Sopenharmony_ci            self.assertNotIn("ERROR", result.stderr)
1476cc1dc7a3Sopenharmony_ci            return
1477cc1dc7a3Sopenharmony_ci
1478cc1dc7a3Sopenharmony_ci        # If we got a negative that's always bad (signal of some kind)
1479cc1dc7a3Sopenharmony_ci        if rcode < 0:
1480cc1dc7a3Sopenharmony_ci            msg = "Exec died with signal %s" % signal.Signals(-rcode).name
1481cc1dc7a3Sopenharmony_ci            self.assertGreaterEqual(rcode, 0, msg)
1482cc1dc7a3Sopenharmony_ci
1483cc1dc7a3Sopenharmony_ci        # Otherwise just assert that we got an error log, and some positive
1484cc1dc7a3Sopenharmony_ci        # return code value was returned
1485cc1dc7a3Sopenharmony_ci        self.assertIn("ERROR", result.stderr)
1486cc1dc7a3Sopenharmony_ci        self.assertGreater(rcode, 0, "Exec did not fail as expected")
1487cc1dc7a3Sopenharmony_ci
1488cc1dc7a3Sopenharmony_ci    def exec_with_omit(self, command, startOmit):
1489cc1dc7a3Sopenharmony_ci        """
1490cc1dc7a3Sopenharmony_ci        Execute a negative test with command line argument omission.
1491cc1dc7a3Sopenharmony_ci
1492cc1dc7a3Sopenharmony_ci        These tests aim to prove that the command fails if arguments are
1493cc1dc7a3Sopenharmony_ci        missing. However the passed command MUST be a valid command which
1494cc1dc7a3Sopenharmony_ci        passes if no argument are omitted (this is checked, to ensure that
1495cc1dc7a3Sopenharmony_ci        the test case is a valid test).
1496cc1dc7a3Sopenharmony_ci
1497cc1dc7a3Sopenharmony_ci        Test will automatically fail if:
1498cc1dc7a3Sopenharmony_ci
1499cc1dc7a3Sopenharmony_ci        * A partial command doesn't fail.
1500cc1dc7a3Sopenharmony_ci        * The full command doesn't pass.
1501cc1dc7a3Sopenharmony_ci        """
1502cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1503cc1dc7a3Sopenharmony_ci        commandLen = len(command)
1504cc1dc7a3Sopenharmony_ci        for subLen in range(startOmit, commandLen + 1):
1505cc1dc7a3Sopenharmony_ci            omit = len(command) - subLen
1506cc1dc7a3Sopenharmony_ci            with self.subTest(omit=omit):
1507cc1dc7a3Sopenharmony_ci                testCommand = command[:subLen]
1508cc1dc7a3Sopenharmony_ci                expectPass = omit == 0
1509cc1dc7a3Sopenharmony_ci                self.exec(testCommand, expectPass)
1510cc1dc7a3Sopenharmony_ci
1511cc1dc7a3Sopenharmony_ci    def test_cl_missing_args(self):
1512cc1dc7a3Sopenharmony_ci        """
1513cc1dc7a3Sopenharmony_ci        Test -cl with missing arguments.
1514cc1dc7a3Sopenharmony_ci        """
1515cc1dc7a3Sopenharmony_ci        # Build a valid command
1516cc1dc7a3Sopenharmony_ci        command = [
1517cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1518cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1519cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1520cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1521cc1dc7a3Sopenharmony_ci
1522cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 2)
1523cc1dc7a3Sopenharmony_ci
1524cc1dc7a3Sopenharmony_ci    def test_cl_missing_input(self):
1525cc1dc7a3Sopenharmony_ci        """
1526cc1dc7a3Sopenharmony_ci        Test -cl with a missing input file.
1527cc1dc7a3Sopenharmony_ci        """
1528cc1dc7a3Sopenharmony_ci        # Build a valid command with a missing input file
1529cc1dc7a3Sopenharmony_ci        command = [
1530cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1531cc1dc7a3Sopenharmony_ci            "./Test/Data/missing.png",
1532cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1533cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1534cc1dc7a3Sopenharmony_ci
1535cc1dc7a3Sopenharmony_ci        self.exec(command)
1536cc1dc7a3Sopenharmony_ci
1537cc1dc7a3Sopenharmony_ci    def test_cl_missing_input_array_slice(self):
1538cc1dc7a3Sopenharmony_ci        """
1539cc1dc7a3Sopenharmony_ci        Test -cl with a missing input file in an array slice.
1540cc1dc7a3Sopenharmony_ci        """
1541cc1dc7a3Sopenharmony_ci        # Build a valid command with a missing input file
1542cc1dc7a3Sopenharmony_ci        command = [
1543cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1544cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
1545cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1546cc1dc7a3Sopenharmony_ci            "3x3x3", "-fast", "-zdim", "3"]
1547cc1dc7a3Sopenharmony_ci
1548cc1dc7a3Sopenharmony_ci        self.exec(command)
1549cc1dc7a3Sopenharmony_ci
1550cc1dc7a3Sopenharmony_ci    def test_cl_unknown_input(self):
1551cc1dc7a3Sopenharmony_ci        """
1552cc1dc7a3Sopenharmony_ci        Test -cl with an unknown input file extension.
1553cc1dc7a3Sopenharmony_ci        """
1554cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1555cc1dc7a3Sopenharmony_ci        command = [
1556cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1557cc1dc7a3Sopenharmony_ci            "./Test/Data/empty.unk",
1558cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1559cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1560cc1dc7a3Sopenharmony_ci
1561cc1dc7a3Sopenharmony_ci        self.exec(command)
1562cc1dc7a3Sopenharmony_ci
1563cc1dc7a3Sopenharmony_ci    def test_cl_missing_output(self):
1564cc1dc7a3Sopenharmony_ci        """
1565cc1dc7a3Sopenharmony_ci        Test -cl with a missing output directory.
1566cc1dc7a3Sopenharmony_ci        """
1567cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1568cc1dc7a3Sopenharmony_ci        command = [
1569cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1570cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1571cc1dc7a3Sopenharmony_ci            "./DoesNotExist/test.astc",
1572cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1573cc1dc7a3Sopenharmony_ci
1574cc1dc7a3Sopenharmony_ci        self.exec(command)
1575cc1dc7a3Sopenharmony_ci
1576cc1dc7a3Sopenharmony_ci    def test_cl_unknown_output(self):
1577cc1dc7a3Sopenharmony_ci        """
1578cc1dc7a3Sopenharmony_ci        Test -cl with an unknown output file extension.
1579cc1dc7a3Sopenharmony_ci        """
1580cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1581cc1dc7a3Sopenharmony_ci        command = [
1582cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1583cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1584cc1dc7a3Sopenharmony_ci            "./test.aastc",
1585cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1586cc1dc7a3Sopenharmony_ci
1587cc1dc7a3Sopenharmony_ci        self.exec(command)
1588cc1dc7a3Sopenharmony_ci
1589cc1dc7a3Sopenharmony_ci    def test_cl_bad_block_size(self):
1590cc1dc7a3Sopenharmony_ci        """
1591cc1dc7a3Sopenharmony_ci        Test -cl with an invalid block size.
1592cc1dc7a3Sopenharmony_ci        """
1593cc1dc7a3Sopenharmony_ci        badSizes = [
1594cc1dc7a3Sopenharmony_ci            "4x5",      # Illegal 2D block size
1595cc1dc7a3Sopenharmony_ci            "3x3x4",    # Illegal 3D block size
1596cc1dc7a3Sopenharmony_ci            "4x4x4x4",  # Too many dimensions
1597cc1dc7a3Sopenharmony_ci            "4x",       # Incomplete 2D block size
1598cc1dc7a3Sopenharmony_ci            "4x4x",     # Incomplete 3D block size
1599cc1dc7a3Sopenharmony_ci            "4x4x4x",   # Over-long 3D block size
1600cc1dc7a3Sopenharmony_ci            "4xe",      # Illegal non-numeric character
1601cc1dc7a3Sopenharmony_ci            "4x4e"      # Additional non-numeric character
1602cc1dc7a3Sopenharmony_ci        ]
1603cc1dc7a3Sopenharmony_ci
1604cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1605cc1dc7a3Sopenharmony_ci        command = [
1606cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1607cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1608cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1609cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1610cc1dc7a3Sopenharmony_ci
1611cc1dc7a3Sopenharmony_ci        # Test that the underlying command is valid
1612cc1dc7a3Sopenharmony_ci        self.exec(command, True)
1613cc1dc7a3Sopenharmony_ci
1614cc1dc7a3Sopenharmony_ci        blockIndex = command.index("4x4")
1615cc1dc7a3Sopenharmony_ci        for badSize in badSizes:
1616cc1dc7a3Sopenharmony_ci            with self.subTest(blockSize=badSize):
1617cc1dc7a3Sopenharmony_ci                command[blockIndex] = badSize
1618cc1dc7a3Sopenharmony_ci                self.exec(command)
1619cc1dc7a3Sopenharmony_ci
1620cc1dc7a3Sopenharmony_ci    def test_cl_bad_preset(self):
1621cc1dc7a3Sopenharmony_ci        """
1622cc1dc7a3Sopenharmony_ci        Test -cl with an invalid encoding preset.
1623cc1dc7a3Sopenharmony_ci        """
1624cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1625cc1dc7a3Sopenharmony_ci        command = [
1626cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1627cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1628cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1629cc1dc7a3Sopenharmony_ci            "4x4", "-fastt"]
1630cc1dc7a3Sopenharmony_ci
1631cc1dc7a3Sopenharmony_ci        self.exec(command)
1632cc1dc7a3Sopenharmony_ci
1633cc1dc7a3Sopenharmony_ci    def test_cl_bad_argument(self):
1634cc1dc7a3Sopenharmony_ci        """
1635cc1dc7a3Sopenharmony_ci        Test -cl with an unknown additional argument.
1636cc1dc7a3Sopenharmony_ci        """
1637cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1638cc1dc7a3Sopenharmony_ci        command = [
1639cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1640cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1641cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1642cc1dc7a3Sopenharmony_ci            "4x4", "-fast", "-unknown"]
1643cc1dc7a3Sopenharmony_ci
1644cc1dc7a3Sopenharmony_ci        self.exec(command)
1645cc1dc7a3Sopenharmony_ci
1646cc1dc7a3Sopenharmony_ci    def test_cl_2d_block_with_array(self):
1647cc1dc7a3Sopenharmony_ci        """
1648cc1dc7a3Sopenharmony_ci        Test -cl with a 2D block size and 3D input data.
1649cc1dc7a3Sopenharmony_ci        """
1650cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1651cc1dc7a3Sopenharmony_ci
1652cc1dc7a3Sopenharmony_ci        # TODO: This fails late (i.e. the data is still loaded, and we fail
1653cc1dc7a3Sopenharmony_ci        # at processing time when we see a 3D array). We could fail earlier at
1654cc1dc7a3Sopenharmony_ci        # parse time, which might consolidate the error handling code.
1655cc1dc7a3Sopenharmony_ci        command = [
1656cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1657cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
1658cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1659cc1dc7a3Sopenharmony_ci            "4x4", "-fast", "-zdim", "2"]
1660cc1dc7a3Sopenharmony_ci
1661cc1dc7a3Sopenharmony_ci        self.exec(command)
1662cc1dc7a3Sopenharmony_ci
1663cc1dc7a3Sopenharmony_ci    def test_cl_array_missing_args(self):
1664cc1dc7a3Sopenharmony_ci        """
1665cc1dc7a3Sopenharmony_ci        Test -cl with a 2D block size and 3D input data.
1666cc1dc7a3Sopenharmony_ci        """
1667cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command
1668cc1dc7a3Sopenharmony_ci        command = [
1669cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1670cc1dc7a3Sopenharmony_ci            "./Test/Data/Tiles/ldr.png",
1671cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1672cc1dc7a3Sopenharmony_ci            "4x4x4", "-fast", "-zdim", "2"]
1673cc1dc7a3Sopenharmony_ci
1674cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1675cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1676cc1dc7a3Sopenharmony_ci
1677cc1dc7a3Sopenharmony_ci    def test_tl_missing_args(self):
1678cc1dc7a3Sopenharmony_ci        """
1679cc1dc7a3Sopenharmony_ci        Test -tl with missing arguments.
1680cc1dc7a3Sopenharmony_ci        """
1681cc1dc7a3Sopenharmony_ci        # Build a valid command
1682cc1dc7a3Sopenharmony_ci        command = [
1683cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1684cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1685cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
1686cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1687cc1dc7a3Sopenharmony_ci
1688cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1689cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 2)
1690cc1dc7a3Sopenharmony_ci
1691cc1dc7a3Sopenharmony_ci    def test_tl_missing_input(self):
1692cc1dc7a3Sopenharmony_ci        """
1693cc1dc7a3Sopenharmony_ci        Test -tl with a missing input file.
1694cc1dc7a3Sopenharmony_ci        """
1695cc1dc7a3Sopenharmony_ci        # Build a valid command with a missing input file
1696cc1dc7a3Sopenharmony_ci        command = [
1697cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1698cc1dc7a3Sopenharmony_ci            "./Test/Data/missing.png",
1699cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
1700cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1701cc1dc7a3Sopenharmony_ci
1702cc1dc7a3Sopenharmony_ci        self.exec(command)
1703cc1dc7a3Sopenharmony_ci
1704cc1dc7a3Sopenharmony_ci    def test_tl_unknown_input(self):
1705cc1dc7a3Sopenharmony_ci        """
1706cc1dc7a3Sopenharmony_ci        Test -tl with an unknown input file extension.
1707cc1dc7a3Sopenharmony_ci        """
1708cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1709cc1dc7a3Sopenharmony_ci        command = [
1710cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1711cc1dc7a3Sopenharmony_ci            "./Test/Data/empty.unk",
1712cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
1713cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1714cc1dc7a3Sopenharmony_ci
1715cc1dc7a3Sopenharmony_ci        self.exec(command)
1716cc1dc7a3Sopenharmony_ci
1717cc1dc7a3Sopenharmony_ci    def test_tl_missing_output(self):
1718cc1dc7a3Sopenharmony_ci        """
1719cc1dc7a3Sopenharmony_ci        Test -tl with a missing output directory.
1720cc1dc7a3Sopenharmony_ci        """
1721cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1722cc1dc7a3Sopenharmony_ci        command = [
1723cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1724cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1725cc1dc7a3Sopenharmony_ci            "./DoesNotExist/test.png",
1726cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1727cc1dc7a3Sopenharmony_ci
1728cc1dc7a3Sopenharmony_ci        self.exec(command)
1729cc1dc7a3Sopenharmony_ci
1730cc1dc7a3Sopenharmony_ci    def test_tl_bad_block_size(self):
1731cc1dc7a3Sopenharmony_ci        """
1732cc1dc7a3Sopenharmony_ci        Test -tl with an invalid block size.
1733cc1dc7a3Sopenharmony_ci        """
1734cc1dc7a3Sopenharmony_ci        badSizes = [
1735cc1dc7a3Sopenharmony_ci            "4x5",      # Illegal 2D block size
1736cc1dc7a3Sopenharmony_ci            "3x3x4",    # Illegal 3D block size
1737cc1dc7a3Sopenharmony_ci            "4x4x4x4",  # Too many dimensions
1738cc1dc7a3Sopenharmony_ci            "4x",       # Incomplete 2D block size
1739cc1dc7a3Sopenharmony_ci            "4x4x",     # Incomplete 3D block size
1740cc1dc7a3Sopenharmony_ci            "4x4x4x",   # Over-long 3D block size
1741cc1dc7a3Sopenharmony_ci            "4xe",      # Illegal non-numeric character
1742cc1dc7a3Sopenharmony_ci            "4x4e"      # Additional non-numeric character
1743cc1dc7a3Sopenharmony_ci        ]
1744cc1dc7a3Sopenharmony_ci
1745cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1746cc1dc7a3Sopenharmony_ci        command = [
1747cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1748cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1749cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
1750cc1dc7a3Sopenharmony_ci            "4x4", "-fast"]
1751cc1dc7a3Sopenharmony_ci
1752cc1dc7a3Sopenharmony_ci        # Test that the underlying command is valid
1753cc1dc7a3Sopenharmony_ci        self.exec(command, True)
1754cc1dc7a3Sopenharmony_ci
1755cc1dc7a3Sopenharmony_ci        blockIndex = command.index("4x4")
1756cc1dc7a3Sopenharmony_ci        for badSize in badSizes:
1757cc1dc7a3Sopenharmony_ci            with self.subTest(blockSize=badSize):
1758cc1dc7a3Sopenharmony_ci                command[blockIndex] = badSize
1759cc1dc7a3Sopenharmony_ci                self.exec(command)
1760cc1dc7a3Sopenharmony_ci
1761cc1dc7a3Sopenharmony_ci    def test_tl_bad_preset(self):
1762cc1dc7a3Sopenharmony_ci        """
1763cc1dc7a3Sopenharmony_ci        Test -tl with an invalid encoding preset.
1764cc1dc7a3Sopenharmony_ci        """
1765cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1766cc1dc7a3Sopenharmony_ci        command = [
1767cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1768cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1769cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
1770cc1dc7a3Sopenharmony_ci            "4x4", "-fastt"]
1771cc1dc7a3Sopenharmony_ci
1772cc1dc7a3Sopenharmony_ci        self.exec(command)
1773cc1dc7a3Sopenharmony_ci
1774cc1dc7a3Sopenharmony_ci    def test_tl_bad_argument(self):
1775cc1dc7a3Sopenharmony_ci        """
1776cc1dc7a3Sopenharmony_ci        Test -tl with an unknown additional argument.
1777cc1dc7a3Sopenharmony_ci        """
1778cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1779cc1dc7a3Sopenharmony_ci        command = [
1780cc1dc7a3Sopenharmony_ci            self.binary, "-tl",
1781cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1782cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
1783cc1dc7a3Sopenharmony_ci            "4x4", "-fast", "-unknown"]
1784cc1dc7a3Sopenharmony_ci
1785cc1dc7a3Sopenharmony_ci        self.exec(command)
1786cc1dc7a3Sopenharmony_ci
1787cc1dc7a3Sopenharmony_ci    def test_dl_missing_args(self):
1788cc1dc7a3Sopenharmony_ci        """
1789cc1dc7a3Sopenharmony_ci        Test -dl with missing arguments.
1790cc1dc7a3Sopenharmony_ci        """
1791cc1dc7a3Sopenharmony_ci        # Build a valid command
1792cc1dc7a3Sopenharmony_ci        command = [
1793cc1dc7a3Sopenharmony_ci            self.binary, "-dl",
1794cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "comp", "A"),
1795cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp")]
1796cc1dc7a3Sopenharmony_ci
1797cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1798cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 2)
1799cc1dc7a3Sopenharmony_ci
1800cc1dc7a3Sopenharmony_ci    def test_dl_missing_output(self):
1801cc1dc7a3Sopenharmony_ci        """
1802cc1dc7a3Sopenharmony_ci        Test -dl with a missing output directory.
1803cc1dc7a3Sopenharmony_ci        """
1804cc1dc7a3Sopenharmony_ci        # Build an otherwise valid command with the test flaw
1805cc1dc7a3Sopenharmony_ci        command = [
1806cc1dc7a3Sopenharmony_ci            self.binary, "-dl",
1807cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "comp", "A"),
1808cc1dc7a3Sopenharmony_ci            "./DoesNotExist/test.png"]
1809cc1dc7a3Sopenharmony_ci
1810cc1dc7a3Sopenharmony_ci        self.exec(command)
1811cc1dc7a3Sopenharmony_ci
1812cc1dc7a3Sopenharmony_ci    def test_cl_a_missing_args(self):
1813cc1dc7a3Sopenharmony_ci        """
1814cc1dc7a3Sopenharmony_ci        Test -cl with -a and missing arguments.
1815cc1dc7a3Sopenharmony_ci        """
1816cc1dc7a3Sopenharmony_ci        # Build a valid command
1817cc1dc7a3Sopenharmony_ci        command = [
1818cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1819cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1820cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1821cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1822cc1dc7a3Sopenharmony_ci            "-a", "2"]
1823cc1dc7a3Sopenharmony_ci
1824cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1825cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1826cc1dc7a3Sopenharmony_ci
1827cc1dc7a3Sopenharmony_ci    def test_cl_cw_missing_args(self):
1828cc1dc7a3Sopenharmony_ci        """
1829cc1dc7a3Sopenharmony_ci        Test -cl with -cw and missing arguments.
1830cc1dc7a3Sopenharmony_ci        """
1831cc1dc7a3Sopenharmony_ci        # Build a valid command
1832cc1dc7a3Sopenharmony_ci        command = [
1833cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1834cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1835cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1836cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1837cc1dc7a3Sopenharmony_ci            "-cw", "0", "1", "2", "3"]
1838cc1dc7a3Sopenharmony_ci
1839cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1840cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1841cc1dc7a3Sopenharmony_ci
1842cc1dc7a3Sopenharmony_ci    def test_cl_2partitionindexlimit_missing_args(self):
1843cc1dc7a3Sopenharmony_ci        """
1844cc1dc7a3Sopenharmony_ci        Test -cl with -2partitionindexlimit and missing arguments.
1845cc1dc7a3Sopenharmony_ci        """
1846cc1dc7a3Sopenharmony_ci        # Build a valid command
1847cc1dc7a3Sopenharmony_ci        command = [
1848cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1849cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1850cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1851cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1852cc1dc7a3Sopenharmony_ci            "-2partitionindexlimit", "3"]
1853cc1dc7a3Sopenharmony_ci
1854cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1855cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1856cc1dc7a3Sopenharmony_ci
1857cc1dc7a3Sopenharmony_ci    def test_cl_3partitionindexlimit_missing_args(self):
1858cc1dc7a3Sopenharmony_ci        """
1859cc1dc7a3Sopenharmony_ci        Test -cl with -3partitionindexlimit and missing arguments.
1860cc1dc7a3Sopenharmony_ci        """
1861cc1dc7a3Sopenharmony_ci        # Build a valid command
1862cc1dc7a3Sopenharmony_ci        command = [
1863cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1864cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1865cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1866cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1867cc1dc7a3Sopenharmony_ci            "-3partitionindexlimit", "3"]
1868cc1dc7a3Sopenharmony_ci
1869cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1870cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1871cc1dc7a3Sopenharmony_ci
1872cc1dc7a3Sopenharmony_ci    def test_cl_4partitionindexlimit_missing_args(self):
1873cc1dc7a3Sopenharmony_ci        """
1874cc1dc7a3Sopenharmony_ci        Test -cl with -4partitionindexlimit and missing arguments.
1875cc1dc7a3Sopenharmony_ci        """
1876cc1dc7a3Sopenharmony_ci        # Build a valid command
1877cc1dc7a3Sopenharmony_ci        command = [
1878cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1879cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1880cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1881cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1882cc1dc7a3Sopenharmony_ci            "-4partitionindexlimit", "3"]
1883cc1dc7a3Sopenharmony_ci
1884cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1885cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1886cc1dc7a3Sopenharmony_ci
1887cc1dc7a3Sopenharmony_ci    def test_cl_2partitioncandidatelimit_missing_args(self):
1888cc1dc7a3Sopenharmony_ci        """
1889cc1dc7a3Sopenharmony_ci        Test -cl with -2partitioncandidatelimit and missing arguments.
1890cc1dc7a3Sopenharmony_ci        """
1891cc1dc7a3Sopenharmony_ci        # Build a valid command
1892cc1dc7a3Sopenharmony_ci        command = [
1893cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1894cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1895cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1896cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1897cc1dc7a3Sopenharmony_ci            "-2partitioncandidatelimit", "1"]
1898cc1dc7a3Sopenharmony_ci
1899cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1900cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1901cc1dc7a3Sopenharmony_ci
1902cc1dc7a3Sopenharmony_ci    def test_cl_3partitioncandidatelimit_missing_args(self):
1903cc1dc7a3Sopenharmony_ci        """
1904cc1dc7a3Sopenharmony_ci        Test -cl with -3partitioncandidatelimit and missing arguments.
1905cc1dc7a3Sopenharmony_ci        """
1906cc1dc7a3Sopenharmony_ci        # Build a valid command
1907cc1dc7a3Sopenharmony_ci        command = [
1908cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1909cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1910cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1911cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1912cc1dc7a3Sopenharmony_ci            "-3partitioncandidatelimit", "3"]
1913cc1dc7a3Sopenharmony_ci
1914cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1915cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1916cc1dc7a3Sopenharmony_ci
1917cc1dc7a3Sopenharmony_ci
1918cc1dc7a3Sopenharmony_ci    def test_cl_4partitioncandidatelimit_missing_args(self):
1919cc1dc7a3Sopenharmony_ci        """
1920cc1dc7a3Sopenharmony_ci        Test -cl with -4partitioncandidatelimit and missing arguments.
1921cc1dc7a3Sopenharmony_ci        """
1922cc1dc7a3Sopenharmony_ci        # Build a valid command
1923cc1dc7a3Sopenharmony_ci        command = [
1924cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1925cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1926cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1927cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1928cc1dc7a3Sopenharmony_ci            "-4partitioncandidatelimit", "3"]
1929cc1dc7a3Sopenharmony_ci
1930cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1931cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1932cc1dc7a3Sopenharmony_ci
1933cc1dc7a3Sopenharmony_ci    def test_cl_blockmodelimit_missing_args(self):
1934cc1dc7a3Sopenharmony_ci        """
1935cc1dc7a3Sopenharmony_ci        Test -cl with -blockmodelimit and missing arguments.
1936cc1dc7a3Sopenharmony_ci        """
1937cc1dc7a3Sopenharmony_ci        # Build a valid command
1938cc1dc7a3Sopenharmony_ci        command = [
1939cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1940cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1941cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1942cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1943cc1dc7a3Sopenharmony_ci            "-blockmodelimit", "3"]
1944cc1dc7a3Sopenharmony_ci
1945cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1946cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1947cc1dc7a3Sopenharmony_ci
1948cc1dc7a3Sopenharmony_ci    def test_cl_refinementlimit_missing_args(self):
1949cc1dc7a3Sopenharmony_ci        """
1950cc1dc7a3Sopenharmony_ci        Test -cl with -refinementlimit and missing arguments.
1951cc1dc7a3Sopenharmony_ci        """
1952cc1dc7a3Sopenharmony_ci        # Build a valid command
1953cc1dc7a3Sopenharmony_ci        command = [
1954cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1955cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1956cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1957cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1958cc1dc7a3Sopenharmony_ci            "-refinementlimit", "3"]
1959cc1dc7a3Sopenharmony_ci
1960cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1961cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1962cc1dc7a3Sopenharmony_ci
1963cc1dc7a3Sopenharmony_ci    def test_cl_dblimit_missing_args(self):
1964cc1dc7a3Sopenharmony_ci        """
1965cc1dc7a3Sopenharmony_ci        Test -cl with -dblimit and missing arguments.
1966cc1dc7a3Sopenharmony_ci        """
1967cc1dc7a3Sopenharmony_ci        # Build a valid command
1968cc1dc7a3Sopenharmony_ci        command = [
1969cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1970cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1971cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1972cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1973cc1dc7a3Sopenharmony_ci            "-dblimit", "3"]
1974cc1dc7a3Sopenharmony_ci
1975cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1976cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1977cc1dc7a3Sopenharmony_ci
1978cc1dc7a3Sopenharmony_ci    def test_cl_2partitionearlylimit_missing_args(self):
1979cc1dc7a3Sopenharmony_ci        """
1980cc1dc7a3Sopenharmony_ci        Test -cl with -2partitionlimitfactor and missing arguments.
1981cc1dc7a3Sopenharmony_ci        """
1982cc1dc7a3Sopenharmony_ci        # Build a valid command
1983cc1dc7a3Sopenharmony_ci        command = [
1984cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
1985cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
1986cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
1987cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
1988cc1dc7a3Sopenharmony_ci            "-2partitionlimitfactor", "3"]
1989cc1dc7a3Sopenharmony_ci
1990cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
1991cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
1992cc1dc7a3Sopenharmony_ci
1993cc1dc7a3Sopenharmony_ci    def test_cl_3partitionearlylimit_missing_args(self):
1994cc1dc7a3Sopenharmony_ci        """
1995cc1dc7a3Sopenharmony_ci        Test -cl with -3partitionlimitfactor and missing arguments.
1996cc1dc7a3Sopenharmony_ci        """
1997cc1dc7a3Sopenharmony_ci        # Build a valid command
1998cc1dc7a3Sopenharmony_ci        command = [
1999cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
2000cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
2001cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
2002cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2003cc1dc7a3Sopenharmony_ci            "-3partitionlimitfactor", "3"]
2004cc1dc7a3Sopenharmony_ci
2005cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
2006cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
2007cc1dc7a3Sopenharmony_ci
2008cc1dc7a3Sopenharmony_ci    def test_cl_2planeearlylimit_missing_args(self):
2009cc1dc7a3Sopenharmony_ci        """
2010cc1dc7a3Sopenharmony_ci        Test -cl with -2planelimitcorrelation and missing arguments.
2011cc1dc7a3Sopenharmony_ci        """
2012cc1dc7a3Sopenharmony_ci        # Build a valid command
2013cc1dc7a3Sopenharmony_ci        command = [
2014cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
2015cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
2016cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
2017cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2018cc1dc7a3Sopenharmony_ci            "-2planelimitcorrelation", "0.66"]
2019cc1dc7a3Sopenharmony_ci
2020cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
2021cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
2022cc1dc7a3Sopenharmony_ci
2023cc1dc7a3Sopenharmony_ci    def test_cl_esw_missing_args(self):
2024cc1dc7a3Sopenharmony_ci        """
2025cc1dc7a3Sopenharmony_ci        Test -cl with -esw and missing arguments.
2026cc1dc7a3Sopenharmony_ci        """
2027cc1dc7a3Sopenharmony_ci        # Build a valid command
2028cc1dc7a3Sopenharmony_ci        command = [
2029cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
2030cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
2031cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
2032cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2033cc1dc7a3Sopenharmony_ci            "-esw", "rgb1"]
2034cc1dc7a3Sopenharmony_ci
2035cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
2036cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
2037cc1dc7a3Sopenharmony_ci
2038cc1dc7a3Sopenharmony_ci    def test_cl_esw_invalid_swizzle(self):
2039cc1dc7a3Sopenharmony_ci        """
2040cc1dc7a3Sopenharmony_ci        Test -cl with -esw and invalid swizzles.
2041cc1dc7a3Sopenharmony_ci        """
2042cc1dc7a3Sopenharmony_ci        badSwizzles = [
2043cc1dc7a3Sopenharmony_ci            "",  # Short swizzles
2044cc1dc7a3Sopenharmony_ci            "r",
2045cc1dc7a3Sopenharmony_ci            "rr",
2046cc1dc7a3Sopenharmony_ci            "rrr",
2047cc1dc7a3Sopenharmony_ci            "rrrrr",  # Long swizzles
2048cc1dc7a3Sopenharmony_ci        ]
2049cc1dc7a3Sopenharmony_ci
2050cc1dc7a3Sopenharmony_ci        # Create swizzles with all invalid printable ascii codes
2051cc1dc7a3Sopenharmony_ci        good = ["r", "g", "b", "a", "0", "1"]
2052cc1dc7a3Sopenharmony_ci        for channel in string.printable:
2053cc1dc7a3Sopenharmony_ci            if channel not in good:
2054cc1dc7a3Sopenharmony_ci                badSwizzles.append(channel * 4)
2055cc1dc7a3Sopenharmony_ci
2056cc1dc7a3Sopenharmony_ci        # Build a valid base command
2057cc1dc7a3Sopenharmony_ci        command = [
2058cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
2059cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
2060cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
2061cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2062cc1dc7a3Sopenharmony_ci            "-esw", "rgba"]
2063cc1dc7a3Sopenharmony_ci
2064cc1dc7a3Sopenharmony_ci        blockIndex = command.index("rgba")
2065cc1dc7a3Sopenharmony_ci        for badSwizzle in badSwizzles:
2066cc1dc7a3Sopenharmony_ci            with self.subTest(swizzle=badSwizzle):
2067cc1dc7a3Sopenharmony_ci                command[blockIndex] = badSwizzle
2068cc1dc7a3Sopenharmony_ci                self.exec(command)
2069cc1dc7a3Sopenharmony_ci
2070cc1dc7a3Sopenharmony_ci    def test_cl_ssw_missing_args(self):
2071cc1dc7a3Sopenharmony_ci        """
2072cc1dc7a3Sopenharmony_ci        Test -cl with -ssw and missing arguments.
2073cc1dc7a3Sopenharmony_ci        """
2074cc1dc7a3Sopenharmony_ci        # Build a valid command
2075cc1dc7a3Sopenharmony_ci        command = [
2076cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
2077cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
2078cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
2079cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2080cc1dc7a3Sopenharmony_ci            "-ssw", "rgba"]
2081cc1dc7a3Sopenharmony_ci
2082cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
2083cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
2084cc1dc7a3Sopenharmony_ci
2085cc1dc7a3Sopenharmony_ci    def test_cl_ssw_invalid_swizzle(self):
2086cc1dc7a3Sopenharmony_ci        """
2087cc1dc7a3Sopenharmony_ci        Test -cl with -ssw and invalid swizzles.
2088cc1dc7a3Sopenharmony_ci        """
2089cc1dc7a3Sopenharmony_ci        badSwizzles = [
2090cc1dc7a3Sopenharmony_ci            "",  # Short swizzles
2091cc1dc7a3Sopenharmony_ci            "rrrrr",  # Long swizzles
2092cc1dc7a3Sopenharmony_ci        ]
2093cc1dc7a3Sopenharmony_ci
2094cc1dc7a3Sopenharmony_ci        # Create swizzles with all invalid printable ascii codes
2095cc1dc7a3Sopenharmony_ci        good = ["r", "g", "b", "a"]
2096cc1dc7a3Sopenharmony_ci        for channel in string.printable:
2097cc1dc7a3Sopenharmony_ci            if channel not in good:
2098cc1dc7a3Sopenharmony_ci                badSwizzles.append(channel * 4)
2099cc1dc7a3Sopenharmony_ci
2100cc1dc7a3Sopenharmony_ci        # Build a valid base command
2101cc1dc7a3Sopenharmony_ci        command = [
2102cc1dc7a3Sopenharmony_ci            self.binary, "-cl",
2103cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "input", "A"),
2104cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "comp"),
2105cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2106cc1dc7a3Sopenharmony_ci            "-ssw", "rgba"]
2107cc1dc7a3Sopenharmony_ci
2108cc1dc7a3Sopenharmony_ci        blockIndex = command.index("rgba")
2109cc1dc7a3Sopenharmony_ci        for badSwizzle in badSwizzles:
2110cc1dc7a3Sopenharmony_ci            with self.subTest(swizzle=badSwizzle):
2111cc1dc7a3Sopenharmony_ci                command[blockIndex] = badSwizzle
2112cc1dc7a3Sopenharmony_ci                self.exec(command)
2113cc1dc7a3Sopenharmony_ci
2114cc1dc7a3Sopenharmony_ci    def test_dl_dsw_missing_args(self):
2115cc1dc7a3Sopenharmony_ci        """
2116cc1dc7a3Sopenharmony_ci        Test -dl with -dsw and missing arguments.
2117cc1dc7a3Sopenharmony_ci        """
2118cc1dc7a3Sopenharmony_ci        # Build a valid command
2119cc1dc7a3Sopenharmony_ci        command = [
2120cc1dc7a3Sopenharmony_ci            self.binary, "-dl",
2121cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "comp", "A"),
2122cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
2123cc1dc7a3Sopenharmony_ci            "-dsw", "rgb1"]
2124cc1dc7a3Sopenharmony_ci
2125cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
2126cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 5)
2127cc1dc7a3Sopenharmony_ci
2128cc1dc7a3Sopenharmony_ci    def test_dl_dsw_invalid_swizzle(self):
2129cc1dc7a3Sopenharmony_ci        """
2130cc1dc7a3Sopenharmony_ci        Test -dl with -dsw and invalid swizzles.
2131cc1dc7a3Sopenharmony_ci        """
2132cc1dc7a3Sopenharmony_ci        badSwizzles = [
2133cc1dc7a3Sopenharmony_ci            "",  # Short swizzles
2134cc1dc7a3Sopenharmony_ci            "r",
2135cc1dc7a3Sopenharmony_ci            "rr",
2136cc1dc7a3Sopenharmony_ci            "rrr",
2137cc1dc7a3Sopenharmony_ci            "rrrrr",  # Long swizzles
2138cc1dc7a3Sopenharmony_ci        ]
2139cc1dc7a3Sopenharmony_ci
2140cc1dc7a3Sopenharmony_ci        # Create swizzles with all invalid printable ascii codes
2141cc1dc7a3Sopenharmony_ci        good = ["r", "g", "b", "a", "z", "0", "1"]
2142cc1dc7a3Sopenharmony_ci        for channel in string.printable:
2143cc1dc7a3Sopenharmony_ci            if channel not in good:
2144cc1dc7a3Sopenharmony_ci                badSwizzles.append(channel * 4)
2145cc1dc7a3Sopenharmony_ci
2146cc1dc7a3Sopenharmony_ci        # Build a valid base command
2147cc1dc7a3Sopenharmony_ci        command = [
2148cc1dc7a3Sopenharmony_ci            self.binary, "-dl",
2149cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("LDR", "comp", "A"),
2150cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("LDR", "decomp"),
2151cc1dc7a3Sopenharmony_ci            "-dsw", "rgba"]
2152cc1dc7a3Sopenharmony_ci
2153cc1dc7a3Sopenharmony_ci        blockIndex = command.index("rgba")
2154cc1dc7a3Sopenharmony_ci        for badSwizzle in badSwizzles:
2155cc1dc7a3Sopenharmony_ci            with self.subTest(swizzle=badSwizzle):
2156cc1dc7a3Sopenharmony_ci                command[blockIndex] = badSwizzle
2157cc1dc7a3Sopenharmony_ci                self.exec(command)
2158cc1dc7a3Sopenharmony_ci
2159cc1dc7a3Sopenharmony_ci    def test_ch_mpsnr_missing_args(self):
2160cc1dc7a3Sopenharmony_ci        """
2161cc1dc7a3Sopenharmony_ci        Test -ch with -mpsnr and missing arguments.
2162cc1dc7a3Sopenharmony_ci        """
2163cc1dc7a3Sopenharmony_ci        # Build a valid command
2164cc1dc7a3Sopenharmony_ci        command = [
2165cc1dc7a3Sopenharmony_ci            self.binary, "-ch",
2166cc1dc7a3Sopenharmony_ci            self.get_ref_image_path("HDR", "input", "A"),
2167cc1dc7a3Sopenharmony_ci            self.get_tmp_image_path("HDR", "comp"),
2168cc1dc7a3Sopenharmony_ci            "4x4", "-fast",
2169cc1dc7a3Sopenharmony_ci            "-mpsnr", "-5", "5"]
2170cc1dc7a3Sopenharmony_ci
2171cc1dc7a3Sopenharmony_ci        # Run the command, incrementally omitting arguments
2172cc1dc7a3Sopenharmony_ci        self.exec_with_omit(command, 7)
2173cc1dc7a3Sopenharmony_ci
2174cc1dc7a3Sopenharmony_ci
2175cc1dc7a3Sopenharmony_cidef main():
2176cc1dc7a3Sopenharmony_ci    """
2177cc1dc7a3Sopenharmony_ci    The main function.
2178cc1dc7a3Sopenharmony_ci
2179cc1dc7a3Sopenharmony_ci    Returns:
2180cc1dc7a3Sopenharmony_ci        int: The process return code.
2181cc1dc7a3Sopenharmony_ci    """
2182cc1dc7a3Sopenharmony_ci    global g_TestEncoder
2183cc1dc7a3Sopenharmony_ci
2184cc1dc7a3Sopenharmony_ci    parser = argparse.ArgumentParser()
2185cc1dc7a3Sopenharmony_ci
2186cc1dc7a3Sopenharmony_ci    coders = ["none", "neon", "sse2", "sse4.1", "avx2"]
2187cc1dc7a3Sopenharmony_ci    parser.add_argument("--encoder", dest="encoder", default="avx2",
2188cc1dc7a3Sopenharmony_ci                        choices=coders, help="test encoder variant")
2189cc1dc7a3Sopenharmony_ci    args = parser.parse_known_args()
2190cc1dc7a3Sopenharmony_ci
2191cc1dc7a3Sopenharmony_ci    # Set the encoder for this test run
2192cc1dc7a3Sopenharmony_ci    g_TestEncoder = args[0].encoder
2193cc1dc7a3Sopenharmony_ci
2194cc1dc7a3Sopenharmony_ci    # Set the sys.argv to remaining args (leave sys.argv[0] alone)
2195cc1dc7a3Sopenharmony_ci    sys.argv[1:] = args[1]
2196cc1dc7a3Sopenharmony_ci
2197cc1dc7a3Sopenharmony_ci    results = unittest.main(exit=False)
2198cc1dc7a3Sopenharmony_ci    return 0 if results.result.wasSuccessful() else 1
2199cc1dc7a3Sopenharmony_ci
2200cc1dc7a3Sopenharmony_ci
2201cc1dc7a3Sopenharmony_ciif __name__ == "__main__":
2202cc1dc7a3Sopenharmony_ci    sys.exit(main())
2203