From d99f96fe1856207b41fbd122083a44e2ffe98508 Mon Sep 17 00:00:00 2001 From: Marco Antognini Date: Fri, 31 May 2019 11:43:02 +0100 Subject: [PATCH] Improve exit codes (#32) (#297) This patch ensures runTestHarness returns either EXIT_FAILURE or EXIT_SUCCESS to avoid undefined behaviour. --- test_common/harness/testHarness.c | 51 ++++++++++--------- test_common/harness/testHarness.h | 6 ++- .../test_common/harness/testHarness.c | 48 ++++++++--------- .../test_common/harness/testHarness.h | 6 ++- 4 files changed, 60 insertions(+), 51 deletions(-) diff --git a/test_common/harness/testHarness.c b/test_common/harness/testHarness.c index ab029b37..1782f3be 100644 --- a/test_common/harness/testHarness.c +++ b/test_common/harness/testHarness.c @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 The Khronos Group Inc. +// Copyright (c) 2017-2019 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ #include "testHarness.h" #include "compat.h" #include +#include #include #include #include @@ -131,7 +132,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (argc == -1) { test_finish(); - return 0; + return EXIT_FAILURE; } /* Special case: just list the tests */ @@ -156,7 +157,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def log_info( "\t%s\n", testList[i].name ); } test_finish(); - return 0; + return EXIT_SUCCESS; } /* How are we supposed to seed the random # generators? */ @@ -237,7 +238,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def case CL_DEVICE_TYPE_CPU: log_info( "Requesting CPU device " ); break; case CL_DEVICE_TYPE_ACCELERATOR: log_info( "Requesting Accelerator device " ); break; case CL_DEVICE_TYPE_DEFAULT: log_info( "Requesting Default device " ); break; - default: log_error( "Requesting unknown device "); return -1; + default: log_error( "Requesting unknown device "); return EXIT_FAILURE; } log_info( based_on_env_var ? "based on environment variable " : "based on command line " ); log_info( "for platform index %d and device index %d\n", choosen_platform_index, choosen_device_index); @@ -266,7 +267,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def else { log_error( "Error: Unknown CL_MAX_SSE setting: %s\n", env ); - return -2; + return EXIT_FAILURE; } log_info( "*** Environment: CL_MAX_SSE = %s ***\n", env ); @@ -281,14 +282,14 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetPlatformIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } platforms = (cl_platform_id *) malloc( num_platforms * sizeof( cl_platform_id ) ); if (!platforms || choosen_platform_index >= num_platforms) { log_error( "platform index out of range -- choosen_platform_index (%d) >= num_platforms (%d)\n", choosen_platform_index, num_platforms ); test_finish(); - return -1; + return EXIT_FAILURE; } BufferOwningPtr platformsBuf(platforms); @@ -296,7 +297,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetPlatformIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } /* Get the number of requested devices */ @@ -304,14 +305,14 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetDeviceIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); if (!devices || choosen_device_index >= num_devices) { log_error( "device index out of range -- choosen_device_index (%d) >= num_devices (%d)\n", choosen_device_index, num_devices ); test_finish(); - return -1; + return EXIT_FAILURE; } BufferOwningPtr devicesBuf(devices); @@ -321,7 +322,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetDeviceIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } device = devices[choosen_device_index]; @@ -329,7 +330,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if( printDeviceHeader( device ) != CL_SUCCESS ) { test_finish(); - return -1; + return EXIT_FAILURE; } cl_device_fp_config fpconfig = 0; @@ -337,7 +338,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed"); test_finish(); - return -1; + return EXIT_FAILURE; } gFlushDenormsToZero = ( 0 == (fpconfig & CL_FP_DENORM)); @@ -351,7 +352,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" ); test_finish(); - return -1; + return EXIT_FAILURE; } gIsEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); @@ -362,7 +363,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed\n"); test_finish(); - return -1; + return EXIT_FAILURE; } // Check for problems that only embedded will have @@ -378,14 +379,14 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error( err, "Unable to get extensions string size for embedded device" ); test_finish(); - return -1; + return EXIT_FAILURE; } char *extensions_string = (char*) malloc(extensionsStringSize); if( NULL == extensions_string ) { print_error( CL_OUT_OF_HOST_MEMORY, "Unable to allocate storage for extensions string for embedded device" ); test_finish(); - return -1; + return EXIT_FAILURE; } BufferOwningPtr extensions_stringBuf(extensions_string); @@ -393,14 +394,14 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error( err, "Unable to get extensions string for embedded device" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( extensions_string[extensionsStringSize-1] != '\0' ) { log_error( "FAILURE: extensions string for embedded device is not NUL terminated" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( NULL == strstr( extensions_string, "cles_khr_int64" )) @@ -417,7 +418,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { log_error( "FAILURE: unable to get CL_DEVICE_OPENCL_C_VERSION on 1.0 device. (%d)\n", err ); test_finish(); - return -1; + return EXIT_FAILURE; } if( 0 == strncmp( c_version, "OpenCL C 1.0 ", strlen( "OpenCL C 1.0 " ) ) ) @@ -434,7 +435,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error( err, "Unable to obtain device address bits" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( device_address_bits ) log_info( "sizeof( void*) = %d (device)\n", device_address_bits/8 ); @@ -442,7 +443,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { log_error("Invalid device address bit size returned by device.\n"); test_finish(); - return -1; + return EXIT_FAILURE; } @@ -455,9 +456,9 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def case TEST_PASS: break; case TEST_FAIL: - return 1; + return EXIT_FAILURE; case TEST_SKIP: - return 0; + return EXIT_SUCCESS; } } @@ -483,7 +484,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def RestoreFPState( &oldMode ); #endif - return error; + return (error == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } static int find_matching_tests( test_definition testList[], unsigned char selectedTestList[], int testNum, diff --git a/test_common/harness/testHarness.h b/test_common/harness/testHarness.h index 9067d555..4668d68d 100644 --- a/test_common/harness/testHarness.h +++ b/test_common/harness/testHarness.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 The Khronos Group Inc. +// Copyright (c) 2017-2019 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -72,6 +72,8 @@ extern cl_uint gRandomSeed; // Supply a list of functions to test here. This will allocate a CL device, create a context, all that // setup work, and then call each function in turn as dictatated by the passed arguments. +// Returns EXIT_SUCCESS iff all tests succeeded or the tests were listed, +// otherwise return EXIT_FAILURE. extern int runTestHarness( int argc, const char *argv[], int testNum, test_definition testList[], int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps ); @@ -79,6 +81,8 @@ extern int runTestHarness( int argc, const char *argv[], int testNum, test_defin typedef test_status (*DeviceCheckFn)( cl_device_id device ); // Same as runTestHarness, but also supplies a function that checks the created device for required functionality. +// Returns EXIT_SUCCESS iff all tests succeeded or the tests were listed, +// otherwise return EXIT_FAILURE. extern int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_definition testList[], int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps, DeviceCheckFn deviceCheckFn ); diff --git a/test_conformance/compatibility/test_common/harness/testHarness.c b/test_conformance/compatibility/test_common/harness/testHarness.c index 95b57f09..b46be90a 100644 --- a/test_conformance/compatibility/test_common/harness/testHarness.c +++ b/test_conformance/compatibility/test_common/harness/testHarness.c @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 The Khronos Group Inc. +// Copyright (c) 2017-2019 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -154,7 +154,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def log_info( "\t%s\n", testList[i].name ); } test_finish(); - return 0; + return EXIT_SUCCESS; } /* How are we supposed to seed the random # generators? */ @@ -235,7 +235,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def case CL_DEVICE_TYPE_CPU: log_info( "Requesting CPU device " ); break; case CL_DEVICE_TYPE_ACCELERATOR: log_info( "Requesting Accelerator device " ); break; case CL_DEVICE_TYPE_DEFAULT: log_info( "Requesting Default device " ); break; - default: log_error( "Requesting unknown device "); return -1; + default: log_error( "Requesting unknown device "); return EXIT_FAILURE; } log_info( based_on_env_var ? "based on environment variable " : "based on command line " ); log_info( "for platform index %d and device index %d\n", choosen_platform_index, choosen_device_index); @@ -264,7 +264,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def else { log_error( "Error: Unknown CL_MAX_SSE setting: %s\n", env ); - return -2; + return EXIT_FAILURE; } log_info( "*** Environment: CL_MAX_SSE = %s ***\n", env ); @@ -279,21 +279,21 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetPlatformIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } platforms = (cl_platform_id *) malloc( num_platforms * sizeof( cl_platform_id ) ); if (!platforms || choosen_platform_index >= num_platforms) { log_error( "platform index out of range -- choosen_platform_index (%d) >= num_platforms (%d)\n", choosen_platform_index, num_platforms ); test_finish(); - return -1; + return EXIT_FAILURE; } err = clGetPlatformIDs(num_platforms, platforms, NULL); if (err) { print_error(err, "clGetPlatformIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } /* Get the number of requested devices */ @@ -301,14 +301,14 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetDeviceIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } devices = (cl_device_id *) malloc( num_devices * sizeof( cl_device_id ) ); if (!devices || choosen_device_index >= num_devices) { log_error( "device index out of range -- choosen_device_index (%d) >= num_devices (%d)\n", choosen_device_index, num_devices ); test_finish(); - return -1; + return EXIT_FAILURE; } /* Get the requested device */ @@ -316,7 +316,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetDeviceIDs failed"); test_finish(); - return -1; + return EXIT_FAILURE; } device = devices[choosen_device_index]; @@ -328,7 +328,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if( printDeviceHeader( device ) != CL_SUCCESS ) { test_finish(); - return -1; + return EXIT_FAILURE; } cl_device_fp_config fpconfig = 0; @@ -336,7 +336,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def if (err) { print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed"); test_finish(); - return -1; + return EXIT_FAILURE; } gFlushDenormsToZero = ( 0 == (fpconfig & CL_FP_DENORM)); @@ -350,7 +350,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n" ); test_finish(); - return -1; + return EXIT_FAILURE; } gIsEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); @@ -361,7 +361,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error(err, "clGetDeviceInfo for CL_DEVICE_SINGLE_FP_CONFIG failed\n"); test_finish(); - return -1; + return EXIT_FAILURE; } // Check for problems that only embedded will have @@ -377,28 +377,28 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error( err, "Unable to get extensions string size for embedded device" ); test_finish(); - return -1; + return EXIT_FAILURE; } char *extensions_string = (char*) malloc(extensionsStringSize); if( NULL == extensions_string ) { print_error( CL_OUT_OF_HOST_MEMORY, "Unable to allocate storage for extensions string for embedded device" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( (err = clGetDeviceInfo( device, CL_DEVICE_EXTENSIONS, extensionsStringSize, extensions_string, NULL ) )) { print_error( err, "Unable to get extensions string for embedded device" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( extensions_string[extensionsStringSize-1] != '\0' ) { log_error( "FAILURE: extensions string for embedded device is not NUL terminated" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( NULL == strstr( extensions_string, "cles_khr_int64" )) @@ -417,7 +417,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { log_error( "FAILURE: unable to get CL_DEVICE_OPENCL_C_VERSION on 1.0 device. (%d)\n", err ); test_finish(); - return -1; + return EXIT_FAILURE; } if( 0 == strncmp( c_version, "OpenCL C 1.0 ", strlen( "OpenCL C 1.0 " ) ) ) @@ -434,7 +434,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { print_error( err, "Unable to obtain device address bits" ); test_finish(); - return -1; + return EXIT_FAILURE; } if( device_address_bits ) log_info( "sizeof( void*) = %d (device)\n", device_address_bits/8 ); @@ -442,7 +442,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def { log_error("Invalid device address bit size returned by device.\n"); test_finish(); - return -1; + return EXIT_FAILURE; } @@ -455,9 +455,9 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def case TEST_PASS: break; case TEST_FAIL: - return 1; + return EXIT_FAILURE; case TEST_SKIP: - return 0; + return EXIT_SUCCESS; } } @@ -483,7 +483,7 @@ int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_def RestoreFPState( &oldMode ); #endif - return error; + return (error == 0) ? EXIT_SUCCESS : EXIT_FAILURE; } static int find_matching_tests( test_definition testList[], unsigned char selectedTestList[], int testNum, diff --git a/test_conformance/compatibility/test_common/harness/testHarness.h b/test_conformance/compatibility/test_common/harness/testHarness.h index 0a86d8dd..1b4ed58f 100644 --- a/test_conformance/compatibility/test_common/harness/testHarness.h +++ b/test_conformance/compatibility/test_common/harness/testHarness.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 The Khronos Group Inc. +// Copyright (c) 2017-2019 The Khronos Group Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -69,6 +69,8 @@ extern cl_uint gRandomSeed; // Supply a list of functions to test here. This will allocate a CL device, create a context, all that // setup work, and then call each function in turn as dictatated by the passed arguments. +// Returns EXIT_SUCCESS iff all tests succeeded or the tests were listed, +// otherwise return EXIT_FAILURE. extern int runTestHarness(int argc, const char *argv[], int testNum, test_definition testList[], int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps ); @@ -76,6 +78,8 @@ extern int runTestHarness(int argc, const char *argv[], int testNum, test_defini typedef test_status (*DeviceCheckFn)( cl_device_id device ); // Same as runTestHarness, but also supplies a function that checks the created device for required functionality. +// Returns EXIT_SUCCESS iff all tests succeeded or the tests were listed, +// otherwise return EXIT_FAILURE. extern int runTestHarnessWithCheck( int argc, const char *argv[], int testNum, test_definition testList[], int imageSupportRequired, int forceNoContextCreation, cl_command_queue_properties queueProps, DeviceCheckFn deviceCheckFn );