cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

generate-test-runner.pl (5458B)


      1#!/usr/bin/env perl
      2#
      3# Licensed to the Apache Software Foundation (ASF) under one
      4# or more contributor license agreements.  See the NOTICE file
      5# distributed with this work for additional information
      6# regarding copyright ownership.  The ASF licenses this file
      7# to you under the Apache License, Version 2.0 (the
      8# "License"); you may not use this file except in compliance
      9# with the License.  You may obtain a copy of the License at
     10#
     11#   http://www.apache.org/licenses/LICENSE-2.0
     12#
     13# Unless required by applicable law or agreed to in writing,
     14# software distributed under the License is distributed on an
     15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     16# KIND, either express or implied.  See the License for the
     17# specific language governing permissions and limitations
     18# under the License.
     19#
     20
     21#
     22# generate-test-runner.pl
     23#
     24# Generates a test runner for the .c files given on the command line. Each .c
     25# file may declare any number of tests so long as each test uses CUnit and is
     26# declared with the following convention:
     27#
     28# void test_SUITENAME__TESTNAME() {
     29#     ...
     30# }
     31#
     32# where TESTNAME is the arbitrary name of the test and SUITENAME is the
     33# arbitrary name of the test suite that this test belongs to.
     34#
     35# Absolutely all tests MUST follow the above convention if they are to be
     36# picked up by this script. Functions which are not tests MUST NOT follow
     37# the above convention.
     38#
     39
     40use strict;
     41
     42my $num_tests = 0;
     43my %test_suites = ();
     44
     45# Parse all test declarations from given file
     46while (<>) {
     47    if ((my $suite_name, my $test_name) = m/^void\s+test_(\w+)__(\w+)/) {
     48        $num_tests++;
     49        $test_suites{$suite_name} //= ();
     50        push @{$test_suites{$suite_name}}, $test_name;
     51    }
     52}
     53
     54# Bail out if there's nothing to write
     55if ($num_tests == 0) {
     56    die "No unit tests... :(\n";
     57}
     58
     59#
     60# Common test runner header
     61#
     62
     63print <<'END';
     64/*
     65 * Licensed to the Apache Software Foundation (ASF) under one
     66 * or more contributor license agreements.  See the NOTICE file
     67 * distributed with this work for additional information
     68 * regarding copyright ownership.  The ASF licenses this file
     69 * to you under the Apache License, Version 2.0 (the
     70 * "License"); you may not use this file except in compliance
     71 * with the License.  You may obtain a copy of the License at
     72 *
     73 *   http://www.apache.org/licenses/LICENSE-2.0
     74 *
     75 * Unless required by applicable law or agreed to in writing,
     76 * software distributed under the License is distributed on an
     77 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     78 * KIND, either express or implied.  See the License for the
     79 * specific language governing permissions and limitations
     80 * under the License.
     81 */
     82
     83#include <stdlib.h>
     84#include <CUnit/TestRun.h>
     85
     86/**
     87 * The current test number, as required by the TAP format. This value is
     88 * automatically incremented by tap_log_test_completed() after each test is
     89 * run.
     90 */
     91int tap_test_number = 1;
     92
     93/**
     94 * Logs the status of a CUnit test which just completed. This implementation
     95 * logs test completion in TAP format.
     96 *
     97 * @param test
     98 *     The CUnit test which just completed.
     99 *
    100 * @param suite
    101 *     The CUnit test suite associated with the test.
    102 *
    103 * @param failure
    104 *     The head element of the test failure list, or NULL if the test passed.
    105 */
    106static void tap_log_test_completed(const CU_pTest test,
    107        const CU_pSuite suite, const CU_pFailureRecord failure) {
    108
    109    /* Log success/failure in TAP format */
    110    if (failure == NULL)
    111        printf("ok %i - [%s] %s: OK\n",
    112            tap_test_number, suite->pName, test->pName);
    113    else
    114        printf("not ok %i - [%s] %s: Assertion failed on %s:%i: %s\n",
    115            tap_test_number, suite->pName, test->pName,
    116            failure->strFileName, failure->uiLineNumber,
    117            failure->strCondition);
    118
    119    tap_test_number++;
    120
    121}
    122END
    123
    124#
    125# Prototypes for all test functions
    126#
    127
    128while ((my $suite_name, my $test_names) = each (%test_suites)) {
    129    print "\n/* Automatically-generated prototypes for the $suite_name suite */\n";
    130    foreach my $test_name (@{ $test_names }) {
    131        print "void test_${suite_name}__${test_name}();\n";
    132    }
    133}
    134
    135#
    136# Beginning of main() function body for test runner
    137#
    138
    139print <<"END";
    140
    141/* Automatically-generated test runner */
    142int main() {
    143
    144    /* Init CUnit test registry */
    145    if (CU_initialize_registry() != CUE_SUCCESS)
    146        return CU_get_error();
    147END
    148
    149#
    150# Within main(), register each test and its corresponding test suite
    151#
    152
    153while ((my $suite_name, my $test_names) = each (%test_suites)) {
    154
    155    print <<"    END";
    156
    157    /* Create and register all tests for the $suite_name suite */
    158    CU_pSuite $suite_name = CU_add_suite("$suite_name", NULL, NULL);
    159    if ($suite_name == NULL
    160    END
    161
    162    foreach my $test_name (@{ $test_names }) {
    163        print <<"        END";
    164        || CU_add_test($suite_name, "$test_name", test_${suite_name}__${test_name}) == NULL
    165        END
    166    }
    167
    168    print <<"    END";
    169    ) goto cleanup;
    170    END
    171
    172}
    173
    174#
    175# End of main() function
    176#
    177
    178print <<"END";
    179
    180    /* Force line-buffered output to ensure log messages are visible even if
    181     * a test crashes */
    182    setvbuf(stdout, NULL, _IOLBF, 0);
    183    setvbuf(stderr, NULL, _IOLBF, 0);
    184
    185    /* Write TAP header */
    186    printf("1..$num_tests\\n");
    187
    188    /* Run all tests in all suites */
    189    CU_set_test_complete_handler(tap_log_test_completed);
    190    CU_run_all_tests();
    191
    192cleanup:
    193    /* Tests complete */
    194    CU_cleanup_registry();
    195    return CU_get_error();
    196
    197}
    198END
    199