Initial open source release of OpenCL 2.2 CTS.

This commit is contained in:
Kedar Patil
2017-05-16 18:25:37 +05:30
parent 6911ba5116
commit 2821bf1323
1035 changed files with 343518 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
set(MODULE_NAME PRINTF)
set(${MODULE_NAME}_SOURCES
test_printf.c
util_printf.c
../../test_common/harness/errorHelpers.c
../../test_common/harness/threadTesting.c
../../test_common/harness/kernelHelpers.c
../../test_common/harness/typeWrappers.cpp
../../test_common/harness/conversions.c
../../test_common/harness/mt19937.c
../../test_common/harness/msvc9.c
#../../test_common/harness/imageHelpers.cpp
../../test_common/harness/parseParameters.cpp
../../test_common/harness/kernelHelpers.c
)
include(../CMakeCommon.txt)

View File

@@ -0,0 +1,5 @@
project
: requirements
<target-os>windows,<toolset>gcc:<cflags>-xc++
<toolset>msvc:<cflags>"/TP"
;

View File

@@ -0,0 +1,44 @@
ifdef BUILD_WITH_ATF
ATF = -framework ATF
USE_ATF = -DUSE_ATF
endif
SRCS = test_printf.c \
util_printf.c \
../../test_common/harness/mt19937.c \
../../test_common/harness/kernelHelpers.c \
../../test_common/harness/errorHelpers.c \
../../test_common/harness/msvc9.c
DEFINES =
SOURCES = $(abspath $(SRCS))
LIBPATH += -L/System/Library/Frameworks/OpenCL.framework/Libraries
LIBPATH += -L.
FRAMEWORK = $(SOURCES)
HEADERS =
TARGET = test_printf
INCLUDE =
COMPILERFLAGS = -c -Wall -g -O0 -Wshorten-64-to-32
CC = c++
CFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
CXXFLAGS = $(COMPILERFLAGS) ${RC_CFLAGS} ${USE_ATF} $(DEFINES:%=-D%) $(INCLUDE)
LIBRARIES = -framework OpenCL -framework OpenGL -framework GLUT -framework AppKit ${ATF}
OBJECTS := ${SOURCES:.c=.o}
OBJECTS := ${OBJECTS:.cpp=.o}
TARGETOBJECT =
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(RC_CFLAGS) $(OBJECTS) -o $@ $(LIBPATH) $(LIBRARIES)
clean:
rm -f $(TARGET) $(OBJECTS)
.DEFAULT:
@echo The target \"$@\" does not exist in Makefile.

View File

@@ -0,0 +1,813 @@
//
// Copyright (c) 2017 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.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "../../test_common/harness/compat.h"
#include <string.h>
#include <errno.h>
#if ! defined( _WIN32)
#if ! defined( __ANDROID__ )
#include <sys/sysctl.h>
#endif
#include <unistd.h>
#define streamDup(fd1) dup(fd1)
#define streamDup2(fd1,fd2) dup2(fd1,fd2)
#endif
#include <limits.h>
#include "test_printf.h"
#if defined(_WIN32)
#include <io.h>
#define streamDup(fd1) _dup(fd1)
#define streamDup2(fd1,fd2) _dup2(fd1,fd2)
#include "../../test_common/harness/testHarness.h"
#endif
#include "../../test_common/harness/errorHelpers.h"
#include "../../test_common/harness/kernelHelpers.h"
#include "../../test_common/harness/mt19937.h"
#include "../../test_common/harness/parseParameters.h"
typedef unsigned int uint32_t;
//-----------------------------------------
// Static helper functions declaration
//-----------------------------------------
//Stream helper functions
//Associate stdout stream with the file(/tmp/tmpfile):i.e redirect stdout stream to the specific files (/tmp/tmpfile)
static int acquireOutputStream();
//Close the file(/tmp/tmpfile) associated with the stdout stream and disassociates it.
static void releaseOutputStream(int fd);
//Get analysis buffer to verify the correctess of printed data
static void getAnalysisBuffer(char* analysisBuffer);
//Kernel builder helper functions
//Check if the test case is for kernel that has argument
static int isKernelArgument(testCase* pTestCase,size_t testId);
//Check if the test case treats %p format for void*
static int isKernelPFormat(testCase* pTestCase,size_t testId);
//-----------------------------------------
// Static functions declarations
//-----------------------------------------
// Make a program that uses printf for the given type/format,
static cl_program makePrintfProgram(cl_kernel *kernel_ptr, const cl_context context,const unsigned int testId,const unsigned int testNum,bool isLongSupport = true,bool is64bAddrSpace = false);
// Creates and execute the printf test for the given device, context, type/format
static int doTest(cl_command_queue queue, cl_context context, const unsigned int testId, const unsigned int testNum, cl_device_id device,bool isLongSupport = true);
// Check if device supports long
static bool isLongSupported(cl_device_id device_id);
// Check if device address space is 64 bits
static bool is64bAddressSpace(cl_device_id device_id);
//Wait until event status is CL_COMPLETE
int waitForEvent(cl_event* event);
//-----------------------------------------
// Definitions and initializations
//-----------------------------------------
// Tests are broken into the major test which is based on the
// src and cmp type and their corresponding vector types and
// sub tests which is for each individual test. The following
// tracks the subtests
int s_test_cnt = 0;
int s_test_fail = 0;
//-----------------------------------------
// Static helper functions definition
//-----------------------------------------
//-----------------------------------------
// acquireOutputStream
//-----------------------------------------
static int acquireOutputStream()
{
int fd = streamDup(fileno(stdout));
#if (defined(__linux__) || defined(__APPLE__)) && (!defined( __ANDROID__ ))
freopen("/tmp/tmpfile","w",stdout);
#else
freopen("tmpfile","w",stdout);
#endif
return fd;
}
//-----------------------------------------
// releaseOutputStream
//-----------------------------------------
static void releaseOutputStream(int fd)
{
fflush(stdout);
streamDup2(fd,fileno(stdout));
close(fd);
}
//-----------------------------------------
// getAnalysisBuffer
//-----------------------------------------
static void getAnalysisBuffer(char* analysisBuffer)
{
FILE *fp;
memset(analysisBuffer,0,ANALYSIS_BUFFER_SIZE);
#if (defined(__linux__) || defined(__APPLE__)) && (!defined( __ANDROID__ ))
fp = fopen("/tmp/tmpfile","r");
#else
fp = fopen("tmpfile","r");
#endif
if(NULL == fp)
log_error("Failed to open analysis buffer ('%s')\n", strerror(errno));
else
while(fgets(analysisBuffer,ANALYSIS_BUFFER_SIZE , fp) != NULL );
fclose(fp);
}
//-----------------------------------------
// isKernelArgument
//-----------------------------------------
static int isKernelArgument(testCase* pTestCase,size_t testId)
{
return strcmp(pTestCase->_genParameters[testId].addrSpaceArgumentTypeQualifier,"");
}
//-----------------------------------------
// isKernelPFormat
//-----------------------------------------
static int isKernelPFormat(testCase* pTestCase,size_t testId)
{
return strcmp(pTestCase->_genParameters[testId].addrSpacePAdd,"");
}
//-----------------------------------------
// waitForEvent
//-----------------------------------------
int waitForEvent(cl_event* event)
{
cl_int status = CL_SUCCESS;
cl_int eventStatus = CL_QUEUED;
while(eventStatus != CL_COMPLETE)
{
status = clGetEventInfo(
*event,
CL_EVENT_COMMAND_EXECUTION_STATUS,
sizeof(cl_int),
&eventStatus,
NULL);
if(status != CL_SUCCESS)
{
log_error("clGetEventInfo failed");
return status;
}
}
status = clReleaseEvent(*event);
if(status != CL_SUCCESS)
{
log_error("clReleaseEvent failed. (*event)");
return status;
}
return CL_SUCCESS;
}
//-----------------------------------------
// Static helper functions definition
//-----------------------------------------
//-----------------------------------------
// makePrintfProgram
//-----------------------------------------
static cl_program makePrintfProgram(cl_kernel *kernel_ptr, const cl_context context,const unsigned int testId,const unsigned int testNum,bool isLongSupport,bool is64bAddrSpace)
{
int err,i;
cl_program program;
cl_device_id devID;
char buildLog[ 1024 * 128 ];
char testname[256] = {0};
char addrSpaceArgument[256] = {0};
char addrSpacePAddArgument[256] = {0};
//Program Source code for int,float,octal,hexadecimal,char,string
const char *sourceGen[] = {
"__kernel void ", testname,
"(void)\n",
"{\n"
" printf(\"",
allTestCase[testId]->_genParameters[testNum].genericFormat,
"\\n\",",
allTestCase[testId]->_genParameters[testNum].dataRepresentation,
");",
"}\n"
};
//Program Source code for vector
const char *sourceVec[] = {
"__kernel void ", testname,
"(void)\n",
"{\n",
allTestCase[testId]->_genParameters[testNum].dataType,
allTestCase[testId]->_genParameters[testNum].vectorSize,
" tmp = (",
allTestCase[testId]->_genParameters[testNum].dataType,
allTestCase[testId]->_genParameters[testNum].vectorSize,
")",
allTestCase[testId]->_genParameters[testNum].dataRepresentation,
";",
" printf(\"",
allTestCase[testId]->_genParameters[testNum].vectorFormatFlag,
"v",
allTestCase[testId]->_genParameters[testNum].vectorSize,
allTestCase[testId]->_genParameters[testNum].vectorFormatSpecifier,
"\\n\",",
"tmp);",
"}\n"
};
//Program Source code for address space
const char *sourceAddrSpace[] = {
"__kernel void ", testname,"(",addrSpaceArgument,
")\n{\n",
allTestCase[testId]->_genParameters[testNum].addrSpaceVariableTypeQualifier,
"printf(",
allTestCase[testId]->_genParameters[testNum].genericFormat,
",",
allTestCase[testId]->_genParameters[testNum].addrSpaceParameter,
"); ",
addrSpacePAddArgument,
"\n}\n"
};
//Update testname
sprintf(testname,"%s%d","test",testId);
//Update addrSpaceArgument and addrSpacePAddArgument types, based on FULL_PROFILE/EMBEDDED_PROFILE
if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE)
{
sprintf(addrSpaceArgument, "%s",allTestCase[testId]->_genParameters[testNum].addrSpaceArgumentTypeQualifier);
sprintf(addrSpacePAddArgument,allTestCase[testId]->_genParameters[testNum].addrSpacePAdd);
}
if (strlen(addrSpaceArgument) == 0)
sprintf(addrSpaceArgument,"void");
// create program based on its type
if(allTestCase[testId]->_type == TYPE_VECTOR)
{
err = create_single_kernel_helper(context, &program, NULL, sizeof(sourceVec) / sizeof(sourceVec[0]), sourceVec, NULL);
}
else if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE)
{
err = create_single_kernel_helper(context, &program, NULL, sizeof(sourceAddrSpace) / sizeof(sourceAddrSpace[0]), sourceAddrSpace, NULL);
}
else
{
err = create_single_kernel_helper(context, &program, NULL, sizeof(sourceGen) / sizeof(sourceGen[0]), sourceGen, NULL);
}
if (!program || err) {
log_error("create_single_kernel_helper failed\n");
return NULL;
}
*kernel_ptr = clCreateKernel(program, testname, &err);
if ( err ) {
log_error("clCreateKernel failed (%d)\n", err);
return NULL;
}
return program;
}
//-----------------------------------------
// isLongSupported
//-----------------------------------------
static bool isLongSupported(cl_device_id device_id)
{
//profile type && device extention for long support checking
char *profileType = NULL,*devExt = NULL;
size_t tempSize = 0;
cl_int status;
bool extSupport = true;
// Device profile
status = clGetDeviceInfo(
device_id,
CL_DEVICE_PROFILE,
0,
NULL,
&tempSize);
if(status != CL_SUCCESS)
{
log_error("*** clGetDeviceInfo FAILED ***\n\n");
return false;
}
profileType = new char[tempSize];
if(profileType == NULL)
{
log_error("Failed to allocate memory(profileType)");
return false;
}
status = clGetDeviceInfo(
device_id,
CL_DEVICE_PROFILE,
sizeof(char) * tempSize,
profileType,
NULL);
if(!strcmp("EMBEDDED_PROFILE",profileType))
{
// Device extention
status = clGetDeviceInfo(
device_id,
CL_DEVICE_EXTENSIONS,
0,
NULL,
&tempSize);
if(status != CL_SUCCESS)
{
log_error("*** clGetDeviceInfo FAILED ***\n\n");
return false;
}
devExt = new char[tempSize];
if(devExt == NULL)
{
log_error("Failed to allocate memory(devExt)");
return false;
}
status = clGetDeviceInfo(
device_id,
CL_DEVICE_EXTENSIONS,
sizeof(char) * tempSize,
devExt,
NULL);
extSupport = (strstr(devExt,"cles_khr_int64") != NULL);
delete devExt;
delete profileType;
}
return extSupport;
}
//-----------------------------------------
// is64bAddressSpace
//-----------------------------------------
static bool is64bAddressSpace(cl_device_id device_id)
{
cl_int status;
cl_uint addrSpaceB;
// Device profile
status = clGetDeviceInfo(
device_id,
CL_DEVICE_ADDRESS_BITS,
sizeof(cl_uint),
&addrSpaceB,
NULL);
if(status != CL_SUCCESS)
{
log_error("*** clGetDeviceInfo FAILED ***\n\n");
return false;
}
if(addrSpaceB == 64)
return true;
else
return false;
}
//-----------------------------------------
// doTest
//-----------------------------------------
static int doTest(cl_command_queue queue, cl_context context, const unsigned int testId, const unsigned int testNum, cl_device_id device,bool isLongSupport)
{
int err;
cl_program program;
cl_kernel kernel;
cl_mem d_out;
char _analysisBuffer[ANALYSIS_BUFFER_SIZE];
cl_uint out32 = 0;
cl_ulong out64 = 0;
// Define an index space (global work size) of threads for execution.
size_t globalWorkSize[1];
program = makePrintfProgram(&kernel, context,testId,testNum,isLongSupport,is64bAddressSpace(device));
if (!program || !kernel) {
++s_test_fail;
++s_test_cnt;
return -1;
}
//For address space test if there is kernel argument - set it
if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE )
{
if(isKernelArgument(allTestCase[testId],testNum))
{
int a = 2;
cl_mem d_a = clCreateBuffer(context, CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,
sizeof(int), &a, &err);
if(err!= CL_SUCCESS || d_a == NULL) {
log_error("clCreateBuffer failed\n");
goto exit;
}
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_a);
if(err!= CL_SUCCESS) {
log_error("clSetKernelArg failed\n");
goto exit;
}
}
//For address space test if %p is tested
if(isKernelPFormat(allTestCase[testId],testNum))
{
d_out = clCreateBuffer(context, CL_MEM_READ_WRITE,
sizeof(cl_ulong), NULL, &err);
if(err!= CL_SUCCESS || d_out == NULL) {
log_error("clCreateBuffer failed\n");
goto exit;
}
err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_out);
if(err!= CL_SUCCESS) {
log_error("clSetKernelArg failed\n");
goto exit;
}
}
}
globalWorkSize[0] = 1;
cl_event ndrEvt;
err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, globalWorkSize, NULL, 0, NULL,&ndrEvt);
if (err != CL_SUCCESS) {
log_error("\n clEnqueueNDRangeKernel failed errcode:%d\n", err);
++s_test_fail;
goto exit;
}
fflush(stdout);
err = clFlush(queue);
if(err != CL_SUCCESS)
{
log_error("clFlush failed\n");
goto exit;
}
//Wait until kernel finishes its execution and (thus) the output printed from the kernel
//is immidatly printed
err = waitForEvent(&ndrEvt);
if(err != CL_SUCCESS)
{
log_error("waitforEvent failed\n");
goto exit;
}
fflush(stdout);
if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE && isKernelPFormat(allTestCase[testId],testNum))
{
// Read the OpenCL output buffer (d_out) to the host output array (out)
if(!is64bAddressSpace(device))//32-bit address space
{
clEnqueueReadBuffer(queue, d_out, CL_TRUE, 0, sizeof(cl_int),&out32,
0, NULL, NULL);
}
else //64-bit address space
{
clEnqueueReadBuffer(queue, d_out, CL_TRUE, 0, sizeof(cl_ulong),&out64,
0, NULL, NULL);
}
}
//
//Get the output printed from the kernel to _analysisBuffer
//and verify its correctness
getAnalysisBuffer(_analysisBuffer);
if(!is64bAddressSpace(device)) //32-bit address space
{
if(0 != verifyOutputBuffer(_analysisBuffer,allTestCase[testId],testNum,(cl_ulong) out32))
err = ++s_test_fail;
}
else //64-bit address space
{
if(0 != verifyOutputBuffer(_analysisBuffer,allTestCase[testId],testNum,out64))
err = ++s_test_fail;
}
exit:
if(clReleaseKernel(kernel) != CL_SUCCESS)
log_error("clReleaseKernel failed\n");
if(clReleaseProgram(program) != CL_SUCCESS)
log_error("clReleaseProgram failed\n");
++s_test_cnt;
return err;
}
//-----------------------------------------
// printUsage
//-----------------------------------------
static void printUsage( void )
{
log_info("test_printf: [-cghw] [start_test_num] \n");
log_info(" default is to run the full test on the default device\n");
log_info(" start_test_num will start running from that num\n");
}
//-----------------------------------------
// printArch
//-----------------------------------------
static void printArch( void )
{
log_info( "sizeof( void*) = %d\n", (int) sizeof( void *) );
#if defined( __APPLE__ )
#if defined( __ppc__ )
log_info( "ARCH:\tppc\n" );
#elif defined( __ppc64__ )
log_info( "ARCH:\tppc64\n" );
#elif defined( __i386__ )
log_info( "ARCH:\ti386\n" );
#elif defined( __x86_64__ )
log_info( "ARCH:\tx86_64\n" );
#elif defined( __arm__ )
log_info( "ARCH:\tarm\n" );
#else
#error unknown arch
#endif
int type = 0;
size_t typeSize = sizeof( type );
sysctlbyname( "hw.cputype", &type, &typeSize, NULL, 0 );
log_info( "cpu type:\t%d\n", type );
typeSize = sizeof( type );
sysctlbyname( "hw.cpusubtype", &type, &typeSize, NULL, 0 );
log_info( "cpu subtype:\t%d\n", type );
#endif
}
//-----------------------------------------
// notify_callback
//-----------------------------------------
void CL_CALLBACK notify_callback(const char *errinfo, const void *private_info, size_t cb, void *user_data)
{
log_info( "%s\n", errinfo );
}
//-----------------------------------------
// main
//-----------------------------------------
int main(int argc, const char* argv[]) {
int i;
cl_device_type device_type = CL_DEVICE_TYPE_DEFAULT;
cl_platform_id platform_id;
long test_filter_num = 0; // test number to run or 0
const char* exec_testname = NULL;
cl_device_id device_id;
uint32_t device_frequency = 0;
uint32_t compute_devices = 0;
test_start();
argc = parseCustomParam(argc, argv);
if (argc == -1)
{
test_finish();
return -1;
}
// Check the environmental to see if there is device preference
char *device_env = getenv("CL_DEVICE_TYPE");
if (device_env != NULL) {
if( strcmp( device_env, "gpu" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_GPU" ) == 0 )
device_type = CL_DEVICE_TYPE_GPU;
else if( strcmp( device_env, "cpu" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_CPU" ) == 0 )
device_type = CL_DEVICE_TYPE_CPU;
else if( strcmp( device_env, "accelerator" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_ACCELERATOR" ) == 0 )
device_type = CL_DEVICE_TYPE_ACCELERATOR;
else if( strcmp( device_env, "default" ) == 0 || strcmp( device_env, "CL_DEVICE_TYPE_DEFAULT" ) == 0 )
device_type = CL_DEVICE_TYPE_DEFAULT;
else
{
log_error( "Unknown CL_DEVICE_TYPE environment variable: %s.\nAborting...\n", device_env );
abort();
}
}
// Determine if we want to run a particular test or if we want to
// start running from a certain point and if we want to run on cpu/gpu
// usage: test_printf [test_name] [start test num] [run_long]
// default is to run all tests on the gpu and be short
// test names are of the form printf_testId
for (i=1; i < argc; ++i) {
const char *arg = argv[i];
if (arg == NULL)
break;
if (arg[0] == '-')
{
arg++;
while(*arg != '\0')
{
switch(*arg) {
case 'h':
printUsage();
return 0;
default:
log_error( " <-- unknown flag: %c (0x%2.2x)\n)", *arg, *arg );
printUsage();
return 0;
}
arg++;
}
}
else {
char* t = NULL;
long num = strtol(argv[i], &t, 0);
if (t != argv[i])
test_filter_num = num;
else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_CPU" ) )
device_type = CL_DEVICE_TYPE_CPU;
else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_GPU" ) )
device_type = CL_DEVICE_TYPE_GPU;
else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_ACCELERATOR" ) )
device_type = CL_DEVICE_TYPE_ACCELERATOR;
else if( 0 == strcmp( argv[i], "CL_DEVICE_TYPE_DEFAULT" ) )
device_type = CL_DEVICE_TYPE_DEFAULT;
else {
// assume it is a test name that we want to execute
exec_testname = argv[i];
}
}
}
int err;
int fd = acquireOutputStream();
// Get platform
err = clGetPlatformIDs(1, &platform_id, NULL);
checkErr(err,"clGetPlatformIDs failed");
// Get Device information
err = clGetDeviceIDs(platform_id, device_type, 1, &device_id, 0);
checkErr(err,"clGetComputeDevices");
err = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, NULL);
checkErr(err,"clGetComputeConfigInfo 1");
size_t config_size = sizeof( device_frequency );
#if MULTITHREAD
if( (err = clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, config_size, &compute_devices, NULL )) )
#endif
compute_devices = 1;
config_size = sizeof(device_frequency);
if((err = clGetDeviceInfo(device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY, config_size, &device_frequency, NULL )))
device_frequency = 1;
releaseOutputStream(fd);
log_info( "\nCompute Device info:\n" );
log_info( "\tProcessing with %d devices\n", compute_devices );
log_info( "\tDevice Frequency: %d MHz\n", device_frequency );
printDeviceHeader( device_id );
printArch();
err = check_opencl_version(device_id,1,2);
if( err != CL_SUCCESS ) {
print_missing_feature(err,"printf");
test_finish();
return err;
}
log_info( "Test binary built %s %s\n", __DATE__, __TIME__ );
fd = acquireOutputStream();
cl_context context = clCreateContext(NULL, 1, &device_id, notify_callback, NULL, NULL);
checkNull(context, "clCreateContext");
cl_command_queue queue = clCreateCommandQueueWithProperties(context, device_id, 0, NULL);
checkNull(queue, "clCreateCommandQueue");
// Forall types
for (int testId = 0; testId < TYPE_COUNT; ++testId) {
if (test_filter_num && (testId != test_filter_num)) {
releaseOutputStream(fd);
log_info("\n*** Skipping printf for %s ***\n",strType[testId]);
fd = acquireOutputStream();
}
else {
releaseOutputStream(fd);
log_info("\n*** Testing printf for %s ***\n",strType[testId]);
fd = acquireOutputStream();
//For all formats
for(unsigned int testNum = 0;testNum < allTestCase[testId]->_testNum;++testNum){
releaseOutputStream(fd);
if(allTestCase[testId]->_type == TYPE_VECTOR)
log_info("%d)testing printf(\"%sv%s%s\",%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].vectorFormatFlag,allTestCase[testId]->_genParameters[testNum].vectorSize,
allTestCase[testId]->_genParameters[testNum].vectorFormatSpecifier,allTestCase[testId]->_genParameters[testNum].dataRepresentation);
else if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE)
{
if(isKernelArgument(allTestCase[testId], testNum))
log_info("%d)testing kernel //argument %s \n printf(%s,%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].addrSpaceArgumentTypeQualifier,
allTestCase[testId]->_genParameters[testNum].genericFormat,allTestCase[testId]->_genParameters[testNum].addrSpaceParameter);
else
log_info("%d)testing kernel //variable %s \n printf(%s,%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].addrSpaceVariableTypeQualifier,
allTestCase[testId]->_genParameters[testNum].genericFormat,allTestCase[testId]->_genParameters[testNum].addrSpaceParameter);
}
else
log_info("%d)testing printf(\"%s\",%s)\n",testNum,allTestCase[testId]->_genParameters[testNum].genericFormat,allTestCase[testId]->_genParameters[testNum].dataRepresentation);
fd = acquireOutputStream();
// Long support for varible type
if(allTestCase[testId]->_type == TYPE_VECTOR && !strcmp(allTestCase[testId]->_genParameters[testNum].dataType,"long") && !isLongSupported(device_id))
continue;
// Long support for address in FULL_PROFILE/EMBEDDED_PROFILE
bool isLongSupport = true;
if(allTestCase[testId]->_type == TYPE_ADDRESS_SPACE && isKernelPFormat(allTestCase[testId],testNum) && !isLongSupported(device_id))
isLongSupport = false;
// Perform the test
if (doTest(queue, context,testId,testNum,device_id,isLongSupport) != 0)
{
releaseOutputStream(fd);
log_error("*** FAILED ***\n\n");
fd = acquireOutputStream();
}
else
{
releaseOutputStream(fd);
log_info("Passed\n");
fd = acquireOutputStream();
}
}
}
}
int error = clFinish(queue);
if (error) {
log_error("clFinish failed: %d\n", error);
}
if(clReleaseCommandQueue(queue)!=CL_SUCCESS)
log_error("clReleaseCommandQueue\n");
if(clReleaseContext(context)!= CL_SUCCESS)
log_error("clReleaseContext\n");
releaseOutputStream(fd);
if (s_test_fail == 0) {
if (s_test_cnt > 1)
log_info("PASSED %d of %d tests.\n", s_test_cnt, s_test_cnt);
else
log_info("PASSED test.\n");
} else if (s_test_fail > 0) {
if (s_test_cnt > 1)
{
log_error("FAILED %d of %d tests.\n", s_test_fail, s_test_cnt);
log_info("PASSED %d of %d tests.\n", s_test_cnt - s_test_fail, s_test_cnt);
}
else
log_error(" FAILED test.\n");
}
test_finish();
return s_test_fail;
}

View File

@@ -0,0 +1,133 @@
//
// Copyright (c) 2017 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.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef TESTPRINTF_INCLUDED_H
#define TESTPRINTF_INCLUDED_H
#include "../../test_common/harness/compat.h"
#include <stdio.h>
#include <string.h>
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#include <OpenCL/cl_platform.h>
#else
#include <CL/opencl.h>
#include <CL/cl_platform.h>
#endif
// Enable the test to be used with ATF
#if USE_ATF
// export BUILD_WITH_ATF=1
#include <ATF/ATF.h>
#define test_start() ATFTestStart()
#define log_info ATFLogInfo
#define log_error ATFLogError
#define test_finish() ATFTestFinish()
#else
#define test_start()
#define log_info printf
#define log_error printf
#define test_finish()
#endif // USE_ATF
#define ANALYSIS_BUFFER_SIZE 256
//-----------------------------------------
// Definitions and initializations
//-----------------------------------------
//-----------------------------------------
// Types
//-----------------------------------------
enum Type
{
TYPE_INT,
TYPE_FLOAT,
TYPE_OCTAL,
TYPE_UNSIGNED,
TYPE_HEXADEC,
TYPE_CHAR,
TYPE_STRING,
TYPE_VECTOR,
TYPE_ADDRESS_SPACE,
TYPE_COUNT
};
struct printDataGenParameters
{
const char* genericFormat;
const char* dataRepresentation;
const char* vectorFormatFlag;
const char* vectorFormatSpecifier;
const char* dataType;
const char* vectorSize;
const char* addrSpaceArgumentTypeQualifier;
const char* addrSpaceVariableTypeQualifier;
const char* addrSpaceParameter;
const char* addrSpacePAdd;
};
//-----------------------------------------
//Test Case
//-----------------------------------------
struct testCase
{
unsigned int _testNum; //test number
enum Type _type; //(data)type for test
//const char** _strPrint; //auxiliary data to build the code for kernel source
const char** _correctBuffer; //look-up table for correct results for printf
struct printDataGenParameters* _genParameters; //auxiliary data to build the code for kernel source
};
extern const char* strType[];
extern testCase* allTestCase[];
size_t verifyOutputBuffer(char *analysisBuffer,testCase* pTestCase,size_t testId,cl_ulong pAddr = 0);
// Helpful macros
// The next three functions check on different return values. Returns -1
// if the check failed
#define checkErr(err, msg) \
if (err != CL_SUCCESS) { \
log_error("%s failed errcode:%d\n", msg, err); \
return -1; \
}
#define checkZero(val, msg) \
if (val == 0) { \
log_error("%s failed errcode:%d\n", msg, err); \
return -1; \
}
#define checkNull(ptr, msg) \
if (!ptr) { \
log_error("%s failed\n", msg); \
return -1; \
}
// When a helper returns a negative one, we want to return from main
// with negative one. This helper prevents me from having to write
// this multiple time
#define checkHelperErr(err) \
if (err == -1) { \
return err; \
}
#endif // TESTSPRINTF_INCLUDED_H

View File

@@ -0,0 +1,894 @@
//
// Copyright (c) 2017 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.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "../../test_common/harness/compat.h"
#include "test_printf.h"
#if defined (_WIN32)
#define strtoull _strtoi64
#endif
const char* strType[] = {"int","float","octal","unsigned","hexadecimal","char","string","vector","address space"};
//==================================
// int
//==================================
//------------------------------------------------------
// [string] format | [string] int-data representation |
//------------------------------------------------------
struct printDataGenParameters printIntGenParameters[] = {
//(Minimum)Five-wide,default(right)-justified
{"%5d","10"},
//(Minimum)Five-wide,left-justified
{"%-5d","10"},
//(Minimum)Five-wide,default(right)-justified,zero-filled
{"%05d","10"},
//(Minimum)Five-wide,default(right)-justified,with sign
{"%+5d","10"},
//(Minimum)Five-wide ,left-justified,with sign
{"%-+5d","10"},
//(Minimum)Five-digit(zero-filled in absent digits),default(right)-justified
{"%.5i","100"},
//(Minimum)Six-wide,Five-digit(zero-filled in absent digits),default(right)-justified
{"%6.5i","100"},
//0 and - flag both apper ==>0 is ignored,left-justified,capital I
{"%-06i","100"},
//(Minimum)Six-wide,Five-digit(zero-filled in absent digits),default(right)-justified
{"%06.5i","100"}
};
//------------------------------------------------
// Lookup table - [string]int-correct buffer |
//------------------------------------------------
const char *correctBufferInt[] = {
" 10",
"10 ",
"00010",
" +10",
"+10 ",
"00100",
" 00100",
"100 ",
" 00100"
};
//-----------------------------------------------
//test case for int |
//-----------------------------------------------
testCase testCaseInt = {
sizeof(correctBufferInt)/sizeof(char*),
TYPE_INT,
correctBufferInt,
printIntGenParameters
};
//==============================================
// float
//==============================================
//--------------------------------------------------------
// [string] format | [string] float-data representation |
//--------------------------------------------------------
struct printDataGenParameters printFloatGenParameters[] = {
//Default(right)-justified
{"%f","10.3456"},
//One position after the decimal,default(right)-justified
{"%.1f","10.3456"},
//Two positions after the decimal,default(right)-justified
{"%.2f","10.3456"},
//(Minimum)Eight-wide,three positions after the decimal,default(right)-justified
{"%8.3f","10.3456"},
//(Minimum)Eight-wide,two positions after the decimal,zero-filled,default(right)-justified
{"%08.2f","10.3456"},
//(Minimum)Eight-wide,two positions after the decimal,left-justified
{"%-8.2f","10.3456"},
//(Minimum)Eight-wide,two positions after the decimal,with sign,default(right)-justified
{"%+8.2f","-10.3456"},
//Zero positions after the decimal([floor]rounding),default(right)-justified
{"%.0f","0.1"},
//Zero positions after the decimal([ceil]rounding),default(right)-justified
{"%.0f","0.6"},
//Zero-filled,default positions number after the decimal,default(right)-justified
{"%0f","0.6"},
//Double argument representing floating-point,used by f style,default(right)-justified
{"%4g","12345.6789"},
//Double argument representing floating-point,used by e style,default(right)-justified
{"%4.2g","12345.6789"},
//Double argument representing floating-point,used by f style,default(right)-justified
{"%4G","0.0000023"},
//Double argument representing floating-point,used by e style,default(right)-justified
{"%4G","0.023"},
//Double argument representing floating-point,with exponent,left-justified,default(right)-justified
{"%-#20.15e","789456123.0"},
//Double argument representing floating-point,with exponent,left-justified,with sign,capital E,default(right)-justified
{"%+#21.15E","789456123.0"},
#if ! defined( __ANDROID__ )
//Double argument representing floating-point,in [-]xh.hhhhpAd style
{"%.6a","0.1"},
//(Minimum)Ten-wide,Double argument representing floating-point,in xh.hhhhpAd style,default(right)-justified
{"%10.2a","9990.235"},
#endif
//Infinity (1.0/0.0)
{"%f","1.0f/0.0f"},
//NaN
{"%f","sqrt(-1.0f)"},
//NaN
{"%f","acospi(2.0f)"}
};
//--------------------------------------------------------
// Lookup table - [string]float-correct buffer |
//--------------------------------------------------------
const char* correctBufferFloat[] = {
"10.345600",
"10.3",
"10.35",
" 10.346",
"00010.35",
"10.35 ",
" -10.35",
"0",
"1",
"0.600000",
"12345.7",
"1.2e+4",
"2.3E-6",
"0.023",
"7.894561230000000e+8",
"+7.894561230000000E+8",
#if ! defined( __ANDROID__ )
"0x1.99999ap-4",
"0x1.38p+13",
#endif
"inf",
"-nan",
"nan"
};
//---------------------------------------------------------
//Test case for float |
//---------------------------------------------------------
testCase testCaseFloat = {
sizeof(correctBufferFloat)/sizeof(char*),
TYPE_FLOAT,
correctBufferFloat,
printFloatGenParameters
};
//=========================================================
// octal
//=========================================================
//---------------------------------------------------------
// [string] format | [string] octal-data representation |
//---------------------------------------------------------
struct printDataGenParameters printOctalGenParameters[] = {
//Default(right)-justified
{"%o","10"},
//Five-digit,default(right)-justified
{"%.5o","10"},
//Default(right)-justified,increase precision
{"%#o","100000000"},
//(Minimum)Four-wide,Five-digit,0-flag ignored(because of precision),default(right)-justified
{"%04.5o","10"}
};
//-------------------------------------------------------
// Lookup table - [string] octal-correct buffer |
//-------------------------------------------------------
const char* correctBufferOctal[] = {
"12",
"00012",
"0575360400",
"00012"
};
//-------------------------------------------------------
//Test case for octal |
//-------------------------------------------------------
testCase testCaseOctal = {
sizeof(correctBufferOctal)/sizeof(char*),
TYPE_OCTAL,
correctBufferOctal,
printOctalGenParameters
};
//=========================================================
// unsigned
//=========================================================
//---------------------------------------------------------
// [string] format | [string] unsined-data representation |
//---------------------------------------------------------
struct printDataGenParameters printUnsignedGenParameters[] = {
//Default(right)-justified
{"%u","10"},
//Zero precision for zero,default(right)-justified
{"%.0u","0"},
};
//-------------------------------------------------------
// Lookup table - [string] octal-correct buffer |
//-------------------------------------------------------
const char* correctBufferUnsigned[] = {
"10",
""
};
//-------------------------------------------------------
//Test case for octal |
//-------------------------------------------------------
testCase testCaseUnsigned = {
sizeof(correctBufferUnsigned)/sizeof(char*),
TYPE_UNSIGNED,
correctBufferUnsigned,
printUnsignedGenParameters
};
//=======================================================
// hexadecimal
//=======================================================
//--------------------------------------------------------------
// [string] format | [string] hexadecimal-data representation |
//--------------------------------------------------------------
struct printDataGenParameters printHexadecimalGenParameters[] = {
//Add 0x,low x,default(right)-justified
{"%#x","0xABCDEF"},
//Add 0x,capital X,default(right)-justified
{"%#X","0xABCDEF"},
//Not add 0x,if zero,default(right)-justified
{"%#X","0"},
//(Minimum)Eight-wide,default(right)-justified
{"%8x","399"},
//(Minimum)Four-wide,zero-filled,default(right)-justified
{"%04x","399"}
};
//--------------------------------------------------------------
// Lookup table - [string]hexadecimal-correct buffer |
//--------------------------------------------------------------
const char* correctBufferHexadecimal[] = {
"0xabcdef",
"0XABCDEF",
"0",
" 18f",
"018f"
};
//--------------------------------------------------------------
//Test case for hexadecimal |
//--------------------------------------------------------------
testCase testCaseHexadecimal = {
sizeof(correctBufferHexadecimal)/sizeof(char*),
TYPE_HEXADEC,
correctBufferHexadecimal,
printHexadecimalGenParameters
};
//=============================================================
// char
//=============================================================
//-----------------------------------------------------------
// [string] format | [string] string-data representation |
//-----------------------------------------------------------
struct printDataGenParameters printCharGenParameters[] = {
//Four-wide,zero-filled,default(right)-justified
{"%4c","\'1\'"},
//Four-wide,left-justified
{"%-4c","\'1\'"},
//(unsigned) int argument,default(right)-justified
{"%c","66"}
};
//---------------------------------------------------------
// Lookup table -[string] char-correct buffer |
//---------------------------------------------------------
const char * correctBufferChar[] = {
" 1",
"1 ",
"B",
};
//----------------------------------------------------------
//Test case for char |
//----------------------------------------------------------
testCase testCaseChar = {
sizeof(correctBufferChar)/sizeof(char*),
TYPE_CHAR,
correctBufferChar,
printCharGenParameters
};
//==========================================================
// string
//==========================================================
//--------------------------------------------------------
// [string]format | [string] string-data representation |
//--------------------------------------------------------
struct printDataGenParameters printStringGenParameters[] = {
//(Minimum)Four-wide,zero-filled,default(right)-justified
{"%4s","\"foo\""},
//One-digit(precision ignored),left-justified
{"%.1s","\"foo\""},
//%% specification
{"%s","\"%%\""},
//null string
{"%s","(void*)0"}
};
//---------------------------------------------------------
// Lookup table -[string] string-correct buffer |
//---------------------------------------------------------
const char * correctBufferString[] = {
" foo",
"f",
"%%",
"(null)"
};
//---------------------------------------------------------
//Test case for string |
//---------------------------------------------------------
testCase testCaseString = {
sizeof(correctBufferString)/sizeof(char*),
TYPE_STRING,
correctBufferString,
printStringGenParameters
};
//=========================================================
// vector
//=========================================================
//-------------------------------------------------------------------------------------------------------------------
//[string] flag | [string] specifier | [string] type | [string] vector-data representation | [string] vector size |
//-------------------------------------------------------------------------------------------------------------------
struct printDataGenParameters printVectorGenParameters[]={
//(Minimum)Two-wide,two positions after decimal
{NULL,"(1.0f,2.0f,3.0f,4.0f)","%2.2","hlf","float","4"},
//Alternative form,uchar argument
{NULL,"(0xFA,0xFB)","%#","hhx","uchar","2"},
//Alternative form,ushort argument
{NULL,"(0x1234,0x8765)","%#","hx","ushort","2"},
//Alternative form,uint argument
{NULL,"(0x12345678,0x87654321)","%#","hlx","uint","2"},
//Alternative form,long argument
{NULL,"(12345678,98765432)","%","ld","long","2"}
};
//------------------------------------------------------------
// Lookup table -[string] vector-correct buffer |
//------------------------------------------------------------
const char * correctBufferVector[] = {
"1.00,2.00,3.00,4.00",
"0xfa,0xfb",
"0x1234,0x8765",
"0x12345678,0x87654321",
"12345678,98765432"
};
//-----------------------------------------------------------
//Test case for vector |
//-----------------------------------------------------------
testCase testCaseVector = {
sizeof(correctBufferVector)/(sizeof(char *)),
TYPE_VECTOR,
correctBufferVector,
printVectorGenParameters
};
//==================================================================
// address space
//==================================================================
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
// [string] argument type qualifier |[string] variable type qualifier + initialization | [string] format | [string] parameter |[string]%p indicator/additional code |
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
struct printDataGenParameters printAddrSpaceGenParameters[]={
//Global memory region
{"\"%d\\n\"",NULL,NULL,NULL,NULL,NULL,"__global int* x","","*x",""},
//Global,constant, memory region
{"\"%d\\n\"",NULL,NULL,NULL,NULL,NULL,"constant int* x","","*x",""},
//Local memory region
{"\"%+d\\n\"",NULL,NULL,NULL,NULL,NULL,"","local int x;\n x= (int)3;\n","x",""},
//Private memory region
{"\"%i\\n\"",NULL,NULL,NULL,NULL,NULL,"","private int x;\n x = (int)-1;\n","x",""},
//Address of void * from global memory region
{"\"%p\\n\"",NULL,NULL,NULL,NULL,NULL,"__global void* x,__global intptr_t* xAddr","","x","*xAddr = (intptr_t)x;\n"}
};
//-------------------------------------------------------------------------------
// Lookup table -[string] address space -correct buffer |
//-------------------------------------------------------------------------------
const char * correctAddrSpace[] = {
"2","2","+3","-1",""
};
//-------------------------------------------------------------------------------
//Test case for address space |
//-------------------------------------------------------------------------------
testCase testCaseAddrSpace = {
sizeof(correctAddrSpace)/(sizeof(char *)),
TYPE_ADDRESS_SPACE,
correctAddrSpace,
printAddrSpaceGenParameters
};
//-------------------------------------------------------------------------------
//All Test cases |
//-------------------------------------------------------------------------------
testCase* allTestCase[] = {&testCaseInt,&testCaseFloat,&testCaseOctal,&testCaseUnsigned,&testCaseHexadecimal,&testCaseChar,&testCaseString,&testCaseVector,&testCaseAddrSpace};
//-----------------------------------------
// Check functions
//-----------------------------------------
size_t verifyOutputBuffer(char *analysisBuffer,testCase* pTestCase,size_t testId,cl_ulong pAddr)
{
int terminatePos = strlen(analysisBuffer);
if(terminatePos > 0)
{
analysisBuffer[terminatePos - 1] = '\0';
}
//Convert analysis buffer to long for address space
if(pTestCase->_type == TYPE_ADDRESS_SPACE && strcmp(pTestCase->_genParameters[testId].addrSpacePAdd,""))
{
char analysisBufferTmp[ANALYSIS_BUFFER_SIZE];
if(strstr(analysisBuffer,"0x") == NULL)
// Need to prepend 0x to ASCII number before calling strtol.
strcpy(analysisBufferTmp,"0x");
else analysisBufferTmp[0]='\0';
strcat(analysisBufferTmp,analysisBuffer);
if (sizeof(long) == 8) {
if(strtoul(analysisBufferTmp,NULL,0) == pAddr) return 0;
}
else {
if(strtoull(analysisBufferTmp,NULL,0) == pAddr) return 0;
}
return 1;
}
char* exp;
//Exponenent representation
if((exp = strstr(analysisBuffer,"E+")) != NULL || (exp = strstr(analysisBuffer,"e+")) != NULL || (exp = strstr(analysisBuffer,"E-")) != NULL || (exp = strstr(analysisBuffer,"e-")) != NULL)
{
char correctExp[3]={0};
strncpy(correctExp,exp,2);
char* eCorrectBuffer = strstr((char*)pTestCase->_correctBuffer[testId],correctExp);
if(eCorrectBuffer == NULL)
return false;
eCorrectBuffer+=2;
exp += 2;
//Exponent always contains at least two digits
if(strlen(exp) < 2)
return false;
//Scip leading zeros in the exponent
while(*exp == '0')
++exp;
return strcmp(eCorrectBuffer,exp);
}
if(!strcmp(pTestCase->_correctBuffer[testId],"inf"))
return strcmp(analysisBuffer,"inf")&&strcmp(analysisBuffer,"infinity")&&strcmp(analysisBuffer,"1.#INF00")&&strcmp(analysisBuffer,"Inf");
if(!strcmp(pTestCase->_correctBuffer[testId],"nan") || !strcmp(pTestCase->_correctBuffer[testId],"-nan")) {
return strcmp(analysisBuffer,"nan")&&strcmp(analysisBuffer,"-nan")&&strcmp(analysisBuffer,"1.#IND00")&&strcmp(analysisBuffer,"-1.#IND00")&&strcmp(analysisBuffer,"NaN")&&strcmp(analysisBuffer,"nan(ind)")&&strcmp(analysisBuffer,"nan(snan)");
}
return strcmp(analysisBuffer,pTestCase->_correctBuffer[testId]);
}