1cc1dc7a3Sopenharmony_ci#!/usr/bin/env python3
2cc1dc7a3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0
3cc1dc7a3Sopenharmony_ci# -----------------------------------------------------------------------------
4cc1dc7a3Sopenharmony_ci# Copyright 2019-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 image test runner is used for image quality and performance testing.
20cc1dc7a3Sopenharmony_ci
21cc1dc7a3Sopenharmony_ciIt is designed to process directories of arbitrary test images, using the
22cc1dc7a3Sopenharmony_cidirectory structure and path naming conventions to self-describe how each image
23cc1dc7a3Sopenharmony_ciis to be compressed. Some built-in test sets are provided in the ./Test/Images
24cc1dc7a3Sopenharmony_cidirectory, and others can be downloaded by running the astc_test_image_dl
25cc1dc7a3Sopenharmony_ciscript.
26cc1dc7a3Sopenharmony_ci
27cc1dc7a3Sopenharmony_ciAttributes:
28cc1dc7a3Sopenharmony_ci    RESULT_THRESHOLD_WARN: The result threshold (dB) for getting a WARN.
29cc1dc7a3Sopenharmony_ci    RESULT_THRESHOLD_FAIL: The result threshold (dB) for getting a FAIL.
30cc1dc7a3Sopenharmony_ci    TEST_BLOCK_SIZES: The block sizes we can test. This is a subset of the
31cc1dc7a3Sopenharmony_ci        block sizes supported by ASTC, simply to keep test run times
32cc1dc7a3Sopenharmony_ci        manageable.
33cc1dc7a3Sopenharmony_ci"""
34cc1dc7a3Sopenharmony_ci
35cc1dc7a3Sopenharmony_ciimport argparse
36cc1dc7a3Sopenharmony_ciimport os
37cc1dc7a3Sopenharmony_ciimport platform
38cc1dc7a3Sopenharmony_ciimport sys
39cc1dc7a3Sopenharmony_ci
40cc1dc7a3Sopenharmony_ciimport testlib.encoder as te
41cc1dc7a3Sopenharmony_ciimport testlib.testset as tts
42cc1dc7a3Sopenharmony_ciimport testlib.resultset as trs
43cc1dc7a3Sopenharmony_ci
44cc1dc7a3Sopenharmony_ci# Require bit exact with reference scores
45cc1dc7a3Sopenharmony_ciRESULT_THRESHOLD_WARN = -0.00
46cc1dc7a3Sopenharmony_ciRESULT_THRESHOLD_FAIL = -0.00
47cc1dc7a3Sopenharmony_ciRESULT_THRESHOLD_3D_FAIL = -0.00
48cc1dc7a3Sopenharmony_ci
49cc1dc7a3Sopenharmony_ci
50cc1dc7a3Sopenharmony_ciTEST_BLOCK_SIZES = ["4x4", "5x5", "6x6", "8x8", "12x12", "3x3x3", "6x6x6"]
51cc1dc7a3Sopenharmony_ci
52cc1dc7a3Sopenharmony_ciTEST_QUALITIES = ["fastest", "fast", "medium", "thorough", "verythorough", "exhaustive"]
53cc1dc7a3Sopenharmony_ci
54cc1dc7a3Sopenharmony_ci
55cc1dc7a3Sopenharmony_cidef is_3d(blockSize):
56cc1dc7a3Sopenharmony_ci    """
57cc1dc7a3Sopenharmony_ci    Is the given block size a 3D block type?
58cc1dc7a3Sopenharmony_ci
59cc1dc7a3Sopenharmony_ci    Args:
60cc1dc7a3Sopenharmony_ci        blockSize (str): The block size.
61cc1dc7a3Sopenharmony_ci
62cc1dc7a3Sopenharmony_ci    Returns:
63cc1dc7a3Sopenharmony_ci        bool: ``True`` if the block string is a 3D block size, ``False`` if 2D.
64cc1dc7a3Sopenharmony_ci    """
65cc1dc7a3Sopenharmony_ci    return blockSize.count("x") == 2
66cc1dc7a3Sopenharmony_ci
67cc1dc7a3Sopenharmony_ci
68cc1dc7a3Sopenharmony_cidef count_test_set(testSet, blockSizes):
69cc1dc7a3Sopenharmony_ci    """
70cc1dc7a3Sopenharmony_ci    Count the number of test executions needed for a test set.
71cc1dc7a3Sopenharmony_ci
72cc1dc7a3Sopenharmony_ci    Args:
73cc1dc7a3Sopenharmony_ci        testSet (TestSet): The test set to run.
74cc1dc7a3Sopenharmony_ci        blockSizes (list(str)): The block sizes to run.
75cc1dc7a3Sopenharmony_ci
76cc1dc7a3Sopenharmony_ci    Returns:
77cc1dc7a3Sopenharmony_ci        int: The number of test executions needed.
78cc1dc7a3Sopenharmony_ci    """
79cc1dc7a3Sopenharmony_ci    count = 0
80cc1dc7a3Sopenharmony_ci    for blkSz in blockSizes:
81cc1dc7a3Sopenharmony_ci        for image in testSet.tests:
82cc1dc7a3Sopenharmony_ci            # 3D block sizes require 3D images
83cc1dc7a3Sopenharmony_ci            if is_3d(blkSz) != image.is3D:
84cc1dc7a3Sopenharmony_ci                continue
85cc1dc7a3Sopenharmony_ci
86cc1dc7a3Sopenharmony_ci            count += 1
87cc1dc7a3Sopenharmony_ci
88cc1dc7a3Sopenharmony_ci    return count
89cc1dc7a3Sopenharmony_ci
90cc1dc7a3Sopenharmony_ci
91cc1dc7a3Sopenharmony_cidef determine_result(image, reference, result):
92cc1dc7a3Sopenharmony_ci    """
93cc1dc7a3Sopenharmony_ci    Determine a test result against a reference and thresholds.
94cc1dc7a3Sopenharmony_ci
95cc1dc7a3Sopenharmony_ci    Args:
96cc1dc7a3Sopenharmony_ci        image (TestImage): The image being compressed.
97cc1dc7a3Sopenharmony_ci        reference (Record): The reference result to compare against.
98cc1dc7a3Sopenharmony_ci        result (Record): The test result.
99cc1dc7a3Sopenharmony_ci
100cc1dc7a3Sopenharmony_ci    Returns:
101cc1dc7a3Sopenharmony_ci        Result: The result code.
102cc1dc7a3Sopenharmony_ci    """
103cc1dc7a3Sopenharmony_ci    dPSNR = result.psnr - reference.psnr
104cc1dc7a3Sopenharmony_ci
105cc1dc7a3Sopenharmony_ci    if (dPSNR < RESULT_THRESHOLD_FAIL) and (not image.is3D):
106cc1dc7a3Sopenharmony_ci        return trs.Result.FAIL
107cc1dc7a3Sopenharmony_ci
108cc1dc7a3Sopenharmony_ci    if (dPSNR < RESULT_THRESHOLD_3D_FAIL) and image.is3D:
109cc1dc7a3Sopenharmony_ci        return trs.Result.FAIL
110cc1dc7a3Sopenharmony_ci
111cc1dc7a3Sopenharmony_ci    if dPSNR < RESULT_THRESHOLD_WARN:
112cc1dc7a3Sopenharmony_ci        return trs.Result.WARN
113cc1dc7a3Sopenharmony_ci
114cc1dc7a3Sopenharmony_ci    return trs.Result.PASS
115cc1dc7a3Sopenharmony_ci
116cc1dc7a3Sopenharmony_ci
117cc1dc7a3Sopenharmony_cidef format_solo_result(image, result):
118cc1dc7a3Sopenharmony_ci    """
119cc1dc7a3Sopenharmony_ci    Format a metrics string for a single (no compare) result.
120cc1dc7a3Sopenharmony_ci
121cc1dc7a3Sopenharmony_ci    Args:
122cc1dc7a3Sopenharmony_ci        image (TestImage): The image being tested.
123cc1dc7a3Sopenharmony_ci        result (Record): The test result.
124cc1dc7a3Sopenharmony_ci
125cc1dc7a3Sopenharmony_ci    Returns:
126cc1dc7a3Sopenharmony_ci        str: The metrics string.
127cc1dc7a3Sopenharmony_ci    """
128cc1dc7a3Sopenharmony_ci    name = "%5s %s" % (result.blkSz, result.name)
129cc1dc7a3Sopenharmony_ci    tPSNR = "%2.3f dB" % result.psnr
130cc1dc7a3Sopenharmony_ci    tTTime = "%.3f s" % result.tTime
131cc1dc7a3Sopenharmony_ci    tCTime = "%.3f s" % result.cTime
132cc1dc7a3Sopenharmony_ci    tCMTS = "%.3f MT/s" % result.cRate
133cc1dc7a3Sopenharmony_ci
134cc1dc7a3Sopenharmony_ci    return "%-32s | %8s | %9s | %9s | %11s" % \
135cc1dc7a3Sopenharmony_ci        (name, tPSNR, tTTime, tCTime, tCMTS)
136cc1dc7a3Sopenharmony_ci
137cc1dc7a3Sopenharmony_ci
138cc1dc7a3Sopenharmony_cidef format_result(image, reference, result):
139cc1dc7a3Sopenharmony_ci    """
140cc1dc7a3Sopenharmony_ci    Format a metrics string for a comparison result.
141cc1dc7a3Sopenharmony_ci
142cc1dc7a3Sopenharmony_ci    Args:
143cc1dc7a3Sopenharmony_ci        image (TestImage): The image being tested.
144cc1dc7a3Sopenharmony_ci        reference (Record): The reference result to compare against.
145cc1dc7a3Sopenharmony_ci        result (Record): The test result.
146cc1dc7a3Sopenharmony_ci
147cc1dc7a3Sopenharmony_ci    Returns:
148cc1dc7a3Sopenharmony_ci        str: The metrics string.
149cc1dc7a3Sopenharmony_ci    """
150cc1dc7a3Sopenharmony_ci    dPSNR = result.psnr - reference.psnr
151cc1dc7a3Sopenharmony_ci    sTTime = reference.tTime / result.tTime
152cc1dc7a3Sopenharmony_ci    sCTime = reference.cTime / result.cTime
153cc1dc7a3Sopenharmony_ci
154cc1dc7a3Sopenharmony_ci    name  = "%5s %s" % (result.blkSz, result.name)
155cc1dc7a3Sopenharmony_ci    tPSNR = "%2.3f dB (% 1.3f dB)" % (result.psnr, dPSNR)
156cc1dc7a3Sopenharmony_ci    tTTime = "%.3f s (%1.2fx)" % (result.tTime, sTTime)
157cc1dc7a3Sopenharmony_ci    tCTime = "%.3f s (%1.2fx)" % (result.cTime, sCTime)
158cc1dc7a3Sopenharmony_ci    tCMTS = "%.3f MT/s" % (result.cRate)
159cc1dc7a3Sopenharmony_ci    result = determine_result(image, reference, result)
160cc1dc7a3Sopenharmony_ci
161cc1dc7a3Sopenharmony_ci    return "%-32s | %22s | %15s | %15s | %11s | %s" % \
162cc1dc7a3Sopenharmony_ci           (name, tPSNR, tTTime, tCTime, tCMTS, result.name)
163cc1dc7a3Sopenharmony_ci
164cc1dc7a3Sopenharmony_ci
165cc1dc7a3Sopenharmony_cidef run_test_set(encoder, testRef, testSet, quality, blockSizes, testRuns,
166cc1dc7a3Sopenharmony_ci                 keepOutput, threads):
167cc1dc7a3Sopenharmony_ci    """
168cc1dc7a3Sopenharmony_ci    Execute all tests in the test set.
169cc1dc7a3Sopenharmony_ci
170cc1dc7a3Sopenharmony_ci    Args:
171cc1dc7a3Sopenharmony_ci        encoder (EncoderBase): The encoder to use.
172cc1dc7a3Sopenharmony_ci        testRef (ResultSet): The test reference results.
173cc1dc7a3Sopenharmony_ci        testSet (TestSet): The test set.
174cc1dc7a3Sopenharmony_ci        quality (str): The quality level to execute the test against.
175cc1dc7a3Sopenharmony_ci        blockSizes (list(str)): The block sizes to execute each test against.
176cc1dc7a3Sopenharmony_ci        testRuns (int): The number of test repeats to run for each image test.
177cc1dc7a3Sopenharmony_ci        keepOutput (bool): Should the test preserve output images? This is
178cc1dc7a3Sopenharmony_ci            only a hint and discarding output may be ignored if the encoder
179cc1dc7a3Sopenharmony_ci            version used can't do it natively.
180cc1dc7a3Sopenharmony_ci        threads (int or None): The thread count to use.
181cc1dc7a3Sopenharmony_ci
182cc1dc7a3Sopenharmony_ci    Returns:
183cc1dc7a3Sopenharmony_ci        ResultSet: The test results.
184cc1dc7a3Sopenharmony_ci    """
185cc1dc7a3Sopenharmony_ci    resultSet = trs.ResultSet(testSet.name)
186cc1dc7a3Sopenharmony_ci
187cc1dc7a3Sopenharmony_ci    curCount = 0
188cc1dc7a3Sopenharmony_ci    maxCount = count_test_set(testSet, blockSizes)
189cc1dc7a3Sopenharmony_ci
190cc1dc7a3Sopenharmony_ci    dat = (testSet.name, encoder.name, quality)
191cc1dc7a3Sopenharmony_ci    title = "Test Set: %s / Encoder: %s -%s" % dat
192cc1dc7a3Sopenharmony_ci    print(title)
193cc1dc7a3Sopenharmony_ci    print("=" * len(title))
194cc1dc7a3Sopenharmony_ci
195cc1dc7a3Sopenharmony_ci    for blkSz in blockSizes:
196cc1dc7a3Sopenharmony_ci        for image in testSet.tests:
197cc1dc7a3Sopenharmony_ci            # 3D block sizes require 3D images
198cc1dc7a3Sopenharmony_ci            if is_3d(blkSz) != image.is3D:
199cc1dc7a3Sopenharmony_ci                continue
200cc1dc7a3Sopenharmony_ci
201cc1dc7a3Sopenharmony_ci            curCount += 1
202cc1dc7a3Sopenharmony_ci
203cc1dc7a3Sopenharmony_ci            dat = (curCount, maxCount, blkSz, image.testFile)
204cc1dc7a3Sopenharmony_ci            print("Running %u/%u %s %s ... " % dat, end='', flush=True)
205cc1dc7a3Sopenharmony_ci            res = encoder.run_test(image, blkSz, "-%s" % quality, testRuns,
206cc1dc7a3Sopenharmony_ci                                   keepOutput, threads)
207cc1dc7a3Sopenharmony_ci            res = trs.Record(blkSz, image.testFile, res[0], res[1], res[2], res[3])
208cc1dc7a3Sopenharmony_ci            resultSet.add_record(res)
209cc1dc7a3Sopenharmony_ci
210cc1dc7a3Sopenharmony_ci            if testRef:
211cc1dc7a3Sopenharmony_ci                refResult = testRef.get_matching_record(res)
212cc1dc7a3Sopenharmony_ci                res.set_status(determine_result(image, refResult, res))
213cc1dc7a3Sopenharmony_ci
214cc1dc7a3Sopenharmony_ci                res.tTimeRel = refResult.tTime / res.tTime
215cc1dc7a3Sopenharmony_ci                res.cTimeRel = refResult.cTime / res.cTime
216cc1dc7a3Sopenharmony_ci                res.psnrRel = res.psnr - refResult.psnr
217cc1dc7a3Sopenharmony_ci
218cc1dc7a3Sopenharmony_ci                res = format_result(image, refResult, res)
219cc1dc7a3Sopenharmony_ci            else:
220cc1dc7a3Sopenharmony_ci                res = format_solo_result(image, res)
221cc1dc7a3Sopenharmony_ci
222cc1dc7a3Sopenharmony_ci            print("\r[%3u] %s" % (curCount, res))
223cc1dc7a3Sopenharmony_ci
224cc1dc7a3Sopenharmony_ci    return resultSet
225cc1dc7a3Sopenharmony_ci
226cc1dc7a3Sopenharmony_ci
227cc1dc7a3Sopenharmony_cidef get_encoder_params(encoderName, referenceName, imageSet):
228cc1dc7a3Sopenharmony_ci    """
229cc1dc7a3Sopenharmony_ci    The the encoder and image set parameters for a test run.
230cc1dc7a3Sopenharmony_ci
231cc1dc7a3Sopenharmony_ci    Args:
232cc1dc7a3Sopenharmony_ci        encoderName (str): The encoder name.
233cc1dc7a3Sopenharmony_ci        referenceName (str): The reference encoder name.
234cc1dc7a3Sopenharmony_ci        imageSet (str): The test image set.
235cc1dc7a3Sopenharmony_ci
236cc1dc7a3Sopenharmony_ci    Returns:
237cc1dc7a3Sopenharmony_ci        tuple(EncoderBase, str, str, str): The test parameters for the
238cc1dc7a3Sopenharmony_ci        requested encoder and test set. An instance of the encoder wrapper
239cc1dc7a3Sopenharmony_ci        class, the output data name, the output result directory, and the
240cc1dc7a3Sopenharmony_ci        reference to use.
241cc1dc7a3Sopenharmony_ci    """
242cc1dc7a3Sopenharmony_ci    # 1.7 variants
243cc1dc7a3Sopenharmony_ci    if encoderName == "ref-1.7":
244cc1dc7a3Sopenharmony_ci        encoder = te.Encoder1_7()
245cc1dc7a3Sopenharmony_ci        name = "reference-1.7"
246cc1dc7a3Sopenharmony_ci        outDir = "Test/Images/%s" % imageSet
247cc1dc7a3Sopenharmony_ci        refName = None
248cc1dc7a3Sopenharmony_ci        return (encoder, name, outDir, refName)
249cc1dc7a3Sopenharmony_ci
250cc1dc7a3Sopenharmony_ci    if encoderName.startswith("ref"):
251cc1dc7a3Sopenharmony_ci        _, version, simd = encoderName.split("-")
252cc1dc7a3Sopenharmony_ci
253cc1dc7a3Sopenharmony_ci        # 2.x, 3.x, and 4.x variants
254cc1dc7a3Sopenharmony_ci        compatible2xPrefixes = ["2.", "3.", "4."]
255cc1dc7a3Sopenharmony_ci        if any(True for x in compatible2xPrefixes if version.startswith(x)):
256cc1dc7a3Sopenharmony_ci            encoder = te.Encoder2xRel(version, simd)
257cc1dc7a3Sopenharmony_ci            name = f"reference-{version}-{simd}"
258cc1dc7a3Sopenharmony_ci            outDir = "Test/Images/%s" % imageSet
259cc1dc7a3Sopenharmony_ci            refName = None
260cc1dc7a3Sopenharmony_ci            return (encoder, name, outDir, refName)
261cc1dc7a3Sopenharmony_ci
262cc1dc7a3Sopenharmony_ci        # Latest main
263cc1dc7a3Sopenharmony_ci        if version == "main":
264cc1dc7a3Sopenharmony_ci            encoder = te.Encoder2x(simd)
265cc1dc7a3Sopenharmony_ci            name = f"reference-{version}-{simd}"
266cc1dc7a3Sopenharmony_ci            outDir = "Test/Images/%s" % imageSet
267cc1dc7a3Sopenharmony_ci            refName = None
268cc1dc7a3Sopenharmony_ci            return (encoder, name, outDir, refName)
269cc1dc7a3Sopenharmony_ci
270cc1dc7a3Sopenharmony_ci        assert False, f"Encoder {encoderName} not recognized"
271cc1dc7a3Sopenharmony_ci
272cc1dc7a3Sopenharmony_ci    encoder = te.Encoder2x(encoderName)
273cc1dc7a3Sopenharmony_ci    name = "develop-%s" % encoderName
274cc1dc7a3Sopenharmony_ci    outDir = "TestOutput/%s" % imageSet
275cc1dc7a3Sopenharmony_ci    refName = referenceName.replace("ref", "reference")
276cc1dc7a3Sopenharmony_ci    return (encoder, name, outDir, refName)
277cc1dc7a3Sopenharmony_ci
278cc1dc7a3Sopenharmony_ci
279cc1dc7a3Sopenharmony_cidef parse_command_line():
280cc1dc7a3Sopenharmony_ci    """
281cc1dc7a3Sopenharmony_ci    Parse the command line.
282cc1dc7a3Sopenharmony_ci
283cc1dc7a3Sopenharmony_ci    Returns:
284cc1dc7a3Sopenharmony_ci        Namespace: The parsed command line container.
285cc1dc7a3Sopenharmony_ci    """
286cc1dc7a3Sopenharmony_ci    parser = argparse.ArgumentParser()
287cc1dc7a3Sopenharmony_ci
288cc1dc7a3Sopenharmony_ci    # All reference encoders
289cc1dc7a3Sopenharmony_ci    refcoders = ["ref-1.7",
290cc1dc7a3Sopenharmony_ci                 "ref-2.5-neon", "ref-2.5-sse2", "ref-2.5-sse4.1", "ref-2.5-avx2",
291cc1dc7a3Sopenharmony_ci                 "ref-3.7-neon", "ref-3.7-sse2", "ref-3.7-sse4.1", "ref-3.7-avx2",
292cc1dc7a3Sopenharmony_ci                 "ref-4.4-neon", "ref-4.4-sse2", "ref-4.4-sse4.1", "ref-4.4-avx2",
293cc1dc7a3Sopenharmony_ci                 "ref-4.5-neon", "ref-4.5-sse2", "ref-4.5-sse4.1", "ref-4.5-avx2",
294cc1dc7a3Sopenharmony_ci                 "ref-main-neon", "ref-main-sse2", "ref-main-sse4.1", "ref-main-avx2"]
295cc1dc7a3Sopenharmony_ci
296cc1dc7a3Sopenharmony_ci    # All test encoders
297cc1dc7a3Sopenharmony_ci    testcoders = ["none", "neon", "sse2", "sse4.1", "avx2", "native", "universal"]
298cc1dc7a3Sopenharmony_ci    testcodersAArch64 = ["neon"]
299cc1dc7a3Sopenharmony_ci    testcodersX86 = ["sse2", "sse4.1", "avx2"]
300cc1dc7a3Sopenharmony_ci
301cc1dc7a3Sopenharmony_ci    coders = refcoders + testcoders + ["all-aarch64", "all-x86"]
302cc1dc7a3Sopenharmony_ci
303cc1dc7a3Sopenharmony_ci    parser.add_argument("--encoder", dest="encoders", default="avx2",
304cc1dc7a3Sopenharmony_ci                        choices=coders, help="test encoder variant")
305cc1dc7a3Sopenharmony_ci
306cc1dc7a3Sopenharmony_ci    parser.add_argument("--reference", dest="reference", default="ref-main-avx2",
307cc1dc7a3Sopenharmony_ci                        choices=refcoders, help="reference encoder variant")
308cc1dc7a3Sopenharmony_ci
309cc1dc7a3Sopenharmony_ci    astcProfile = ["ldr", "ldrs", "hdr", "all"]
310cc1dc7a3Sopenharmony_ci    parser.add_argument("--color-profile", dest="profiles", default="all",
311cc1dc7a3Sopenharmony_ci                        choices=astcProfile, help="test color profile")
312cc1dc7a3Sopenharmony_ci
313cc1dc7a3Sopenharmony_ci    imgFormat = ["l", "xy", "rgb", "rgba", "all"]
314cc1dc7a3Sopenharmony_ci    parser.add_argument("--color-format", dest="formats", default="all",
315cc1dc7a3Sopenharmony_ci                        choices=imgFormat, help="test color format")
316cc1dc7a3Sopenharmony_ci
317cc1dc7a3Sopenharmony_ci    choices = list(TEST_BLOCK_SIZES) + ["all"]
318cc1dc7a3Sopenharmony_ci    parser.add_argument("--block-size", dest="blockSizes",
319cc1dc7a3Sopenharmony_ci                        action="append", choices=choices,
320cc1dc7a3Sopenharmony_ci                        help="test block size")
321cc1dc7a3Sopenharmony_ci
322cc1dc7a3Sopenharmony_ci    testDir = os.path.dirname(__file__)
323cc1dc7a3Sopenharmony_ci    testDir = os.path.join(testDir, "Images")
324cc1dc7a3Sopenharmony_ci    testSets = []
325cc1dc7a3Sopenharmony_ci    for path in os.listdir(testDir):
326cc1dc7a3Sopenharmony_ci        fqPath = os.path.join(testDir, path)
327cc1dc7a3Sopenharmony_ci        if os.path.isdir(fqPath):
328cc1dc7a3Sopenharmony_ci            testSets.append(path)
329cc1dc7a3Sopenharmony_ci    testSets.append("all")
330cc1dc7a3Sopenharmony_ci
331cc1dc7a3Sopenharmony_ci    parser.add_argument("--test-set", dest="testSets", default="Small",
332cc1dc7a3Sopenharmony_ci                        choices=testSets, help="test image test set")
333cc1dc7a3Sopenharmony_ci
334cc1dc7a3Sopenharmony_ci    parser.add_argument("--test-image", dest="testImage", default=None,
335cc1dc7a3Sopenharmony_ci                        help="select a specific test image from the test set")
336cc1dc7a3Sopenharmony_ci
337cc1dc7a3Sopenharmony_ci    choices = list(TEST_QUALITIES) + ["all", "all+"]
338cc1dc7a3Sopenharmony_ci    parser.add_argument("--test-quality", dest="testQual", default="thorough",
339cc1dc7a3Sopenharmony_ci                        choices=choices, help="select a specific test quality")
340cc1dc7a3Sopenharmony_ci
341cc1dc7a3Sopenharmony_ci    parser.add_argument("--repeats", dest="testRepeats", default=1,
342cc1dc7a3Sopenharmony_ci                        type=int, help="test iteration count")
343cc1dc7a3Sopenharmony_ci
344cc1dc7a3Sopenharmony_ci    parser.add_argument("--keep-output", dest="keepOutput", default=False,
345cc1dc7a3Sopenharmony_ci                        action="store_true", help="keep image output")
346cc1dc7a3Sopenharmony_ci
347cc1dc7a3Sopenharmony_ci    parser.add_argument("-j", dest="threads", default=None,
348cc1dc7a3Sopenharmony_ci                        type=int, help="thread count")
349cc1dc7a3Sopenharmony_ci
350cc1dc7a3Sopenharmony_ci
351cc1dc7a3Sopenharmony_ci    args = parser.parse_args()
352cc1dc7a3Sopenharmony_ci
353cc1dc7a3Sopenharmony_ci    # Turn things into canonical format lists
354cc1dc7a3Sopenharmony_ci    if args.encoders == "all-aarch64":
355cc1dc7a3Sopenharmony_ci        args.encoders = testcodersAArch64
356cc1dc7a3Sopenharmony_ci    elif args.encoders == "all-x86":
357cc1dc7a3Sopenharmony_ci        args.encoders = testcodersX86
358cc1dc7a3Sopenharmony_ci    else:
359cc1dc7a3Sopenharmony_ci        args.encoders = [args.encoders]
360cc1dc7a3Sopenharmony_ci
361cc1dc7a3Sopenharmony_ci    if args.testQual == "all+":
362cc1dc7a3Sopenharmony_ci        args.testQual = TEST_QUALITIES
363cc1dc7a3Sopenharmony_ci    elif args.testQual == "all":
364cc1dc7a3Sopenharmony_ci        args.testQual = TEST_QUALITIES
365cc1dc7a3Sopenharmony_ci        args.testQual.remove("verythorough")
366cc1dc7a3Sopenharmony_ci        args.testQual.remove("exhaustive")
367cc1dc7a3Sopenharmony_ci    else:
368cc1dc7a3Sopenharmony_ci        args.testQual = [args.testQual]
369cc1dc7a3Sopenharmony_ci
370cc1dc7a3Sopenharmony_ci    if not args.blockSizes or ("all" in args.blockSizes):
371cc1dc7a3Sopenharmony_ci        args.blockSizes = TEST_BLOCK_SIZES
372cc1dc7a3Sopenharmony_ci
373cc1dc7a3Sopenharmony_ci    args.testSets = testSets[:-1] if args.testSets == "all" \
374cc1dc7a3Sopenharmony_ci        else [args.testSets]
375cc1dc7a3Sopenharmony_ci
376cc1dc7a3Sopenharmony_ci    args.profiles = astcProfile[:-1] if args.profiles == "all" \
377cc1dc7a3Sopenharmony_ci        else [args.profiles]
378cc1dc7a3Sopenharmony_ci
379cc1dc7a3Sopenharmony_ci    args.formats = imgFormat[:-1] if args.formats == "all" \
380cc1dc7a3Sopenharmony_ci        else [args.formats]
381cc1dc7a3Sopenharmony_ci
382cc1dc7a3Sopenharmony_ci    return args
383cc1dc7a3Sopenharmony_ci
384cc1dc7a3Sopenharmony_ci
385cc1dc7a3Sopenharmony_cidef main():
386cc1dc7a3Sopenharmony_ci    """
387cc1dc7a3Sopenharmony_ci    The main function.
388cc1dc7a3Sopenharmony_ci
389cc1dc7a3Sopenharmony_ci    Returns:
390cc1dc7a3Sopenharmony_ci        int: The process return code.
391cc1dc7a3Sopenharmony_ci    """
392cc1dc7a3Sopenharmony_ci    # Parse command lines
393cc1dc7a3Sopenharmony_ci    args = parse_command_line()
394cc1dc7a3Sopenharmony_ci
395cc1dc7a3Sopenharmony_ci    testSetCount = 0
396cc1dc7a3Sopenharmony_ci    worstResult = trs.Result.NOTRUN
397cc1dc7a3Sopenharmony_ci
398cc1dc7a3Sopenharmony_ci    for quality in args.testQual:
399cc1dc7a3Sopenharmony_ci        for imageSet in args.testSets:
400cc1dc7a3Sopenharmony_ci            for encoderName in args.encoders:
401cc1dc7a3Sopenharmony_ci                (encoder, name, outDir, refName) = \
402cc1dc7a3Sopenharmony_ci                    get_encoder_params(encoderName, args.reference, imageSet)
403cc1dc7a3Sopenharmony_ci
404cc1dc7a3Sopenharmony_ci                testDir = "Test/Images/%s" % imageSet
405cc1dc7a3Sopenharmony_ci                testRes = "%s/astc_%s_%s_results.csv" % (outDir, name, quality)
406cc1dc7a3Sopenharmony_ci
407cc1dc7a3Sopenharmony_ci                testRef = None
408cc1dc7a3Sopenharmony_ci                if refName:
409cc1dc7a3Sopenharmony_ci                    dat = (testDir, refName, quality)
410cc1dc7a3Sopenharmony_ci                    testRefPath = "%s/astc_%s_%s_results.csv" % dat
411cc1dc7a3Sopenharmony_ci                    testRef = trs.ResultSet(imageSet)
412cc1dc7a3Sopenharmony_ci                    testRef.load_from_file(testRefPath)
413cc1dc7a3Sopenharmony_ci
414cc1dc7a3Sopenharmony_ci                testSetCount += 1
415cc1dc7a3Sopenharmony_ci                testSet = tts.TestSet(imageSet, testDir,
416cc1dc7a3Sopenharmony_ci                                      args.profiles, args.formats, args.testImage)
417cc1dc7a3Sopenharmony_ci
418cc1dc7a3Sopenharmony_ci                resultSet = run_test_set(encoder, testRef, testSet, quality,
419cc1dc7a3Sopenharmony_ci                                         args.blockSizes, args.testRepeats,
420cc1dc7a3Sopenharmony_ci                                         args.keepOutput, args.threads)
421cc1dc7a3Sopenharmony_ci
422cc1dc7a3Sopenharmony_ci                resultSet.save_to_file(testRes)
423cc1dc7a3Sopenharmony_ci
424cc1dc7a3Sopenharmony_ci                if refName:
425cc1dc7a3Sopenharmony_ci                    summary = resultSet.get_results_summary()
426cc1dc7a3Sopenharmony_ci                    worstResult = max(summary.get_worst_result(), worstResult)
427cc1dc7a3Sopenharmony_ci                    print(summary)
428cc1dc7a3Sopenharmony_ci
429cc1dc7a3Sopenharmony_ci        if (testSetCount > 1) and (worstResult != trs.Result.NOTRUN):
430cc1dc7a3Sopenharmony_ci            print("OVERALL STATUS: %s" % worstResult.name)
431cc1dc7a3Sopenharmony_ci
432cc1dc7a3Sopenharmony_ci    if worstResult == trs.Result.FAIL:
433cc1dc7a3Sopenharmony_ci        return 1
434cc1dc7a3Sopenharmony_ci
435cc1dc7a3Sopenharmony_ci    return 0
436cc1dc7a3Sopenharmony_ci
437cc1dc7a3Sopenharmony_ci
438cc1dc7a3Sopenharmony_ciif __name__ == "__main__":
439cc1dc7a3Sopenharmony_ci    sys.exit(main())
440cc1dc7a3Sopenharmony_ci
441cc1dc7a3Sopenharmony_ci
442cc1dc7a3Sopenharmony_ciif __name__ == "__main__":
443cc1dc7a3Sopenharmony_ci    sys.exit(main())
444