/* * Copyright © 2012 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * Author: Benjamin Segovia */ /** * \file utest.cpp * \author Benjamin Segovia */ #include "utest.hpp" #include "utest_helper.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct signalMap { const char* signalName; int signalNum; }; using namespace std; sem_t tag; vector *UTest::utestList = NULL; vector v; // Initialize and declare statistics struct RStatistics UTest::retStatistics; void releaseUTestList(void) { delete UTest::utestList; } void runSummaryAtExit(void) { // If case crashes, count it as fail, and accumulate finishrun if(UTest::retStatistics.finishrun != UTest::utestList->size()) { UTest::retStatistics.finishrun++; // UTest::retStatistics.failCount++; } printf("\nsummary:\n----------\n"); printf(" total: %zu\n",UTest::utestList->size()); printf(" run: %zu\n",UTest::retStatistics.actualrun); printf(" pass: %zu\n",UTest::retStatistics.passCount); printf(" fail: %zu\n",UTest::retStatistics.failCount); printf(" pass rate: %f\n", (UTest::retStatistics.actualrun)?((float)UTest::retStatistics.passCount/(float)UTest::retStatistics.actualrun):(float)0); releaseUTestList(); } void signalHandler( int signum ) { const char* name = ""; signalMap arr[] = { {"SIGILL", SIGILL}, {"SIGFPE", SIGFPE}, {"SIGABRT", SIGABRT}, {"SIGBUS", SIGBUS}, {"SIGSEGV", SIGSEGV}, {"SIGHUP", SIGHUP}, {"SIGINT", SIGINT}, {"SIGQUIT", SIGQUIT}, {"SIGTERM", SIGTERM}, {NULL, -1} }; for(int i=0; arr[i].signalNum != -1 && arr[i].signalName != NULL; i++) { if(arr[i].signalNum == signum) name = arr[i].signalName; } printf(" Interrupt signal (%s) received.", name); UTest::retStatistics.failCount++; exit(signum); } void catch_signal(void){ struct sigaction sa; int sigs[] = { SIGILL, SIGFPE, SIGABRT, SIGBUS, SIGSEGV, SIGHUP, SIGINT, SIGQUIT, SIGTERM }; sa.sa_handler = signalHandler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESETHAND; for(unsigned int i = 0; i < sizeof(sigs)/sizeof(sigs[0]); ++i) { if (sigaction(sigs[i], &sa, NULL) == -1) perror("Could not set signal handler"); } } void *multithread(void * arg) { int SerialNumber; //size_t PhtreadNumber = (size_t)arg; while(! v.empty()){ sem_wait(&tag); SerialNumber = v.back(); v.pop_back(); sem_post(&tag); const UTest &utest = (*UTest::utestList)[SerialNumber]; if (utest.fn == NULL || utest.haveIssue || utest.isBenchMark) continue; // printf("thread%lu %d, utests.name is %s\n",PhtreadNumber, SerialNumber,utest.name); UTest::do_run(utest); cl_kernel_destroy(true); cl_buffer_destroy(); } return 0; } UTest::UTest(Function fn, const char *name, bool isBenchMark, bool haveIssue, bool needDestroyProgram) : fn(fn), name(name), isBenchMark(isBenchMark), haveIssue(haveIssue), needDestroyProgram(needDestroyProgram) { if (utestList == NULL) { utestList = new vector; catch_signal(); atexit(runSummaryAtExit); } utestList->push_back(*this); } static bool strequal(const char *s1, const char *s2) { if (strcmp(s1, s2) == 0) return true; return false; } void UTest::do_run(struct UTest utest){ // Print function name printf("%s()", utest.name); fflush(stdout); retStatistics.actualrun++; // Run one case in utestList, print result [SUCCESS] or [FAILED] (utest.fn)(); } void UTest::run(const char *name) { if (name == NULL) return; if (utestList == NULL) return; for (; retStatistics.finishrun < utestList->size(); ++retStatistics.finishrun) { const UTest &utest = (*utestList)[retStatistics.finishrun]; if (utest.name == NULL || utest.fn == NULL ) continue; if (strequal(utest.name, name)) { do_run(utest); cl_kernel_destroy(true); cl_buffer_destroy(); } } } void UTest::runMultiThread(const char *number) { if (number == NULL) return; if (utestList == NULL) return; unsigned long i, num; sem_init(&tag, 0, 1); num = atoi(number); unsigned long max_num = sysconf(_SC_NPROCESSORS_ONLN); if(num < 1 || num > max_num){ printf("the value range of multi-thread is [1 - %lu]",max_num); return; } for(i = 0; i < utestList->size(); ++i) v.push_back (i); unsigned seed = chrono::system_clock::now ().time_since_epoch ().count (); shuffle (v.begin (), v.end (), std::default_random_engine (seed)); pthread_t pthread_arry[num]; for(i=0; isize(); ++retStatistics.finishrun) { const UTest &utest = (*utestList)[retStatistics.finishrun]; if (utest.fn == NULL) continue; do_run(utest); cl_kernel_destroy(utest.needDestroyProgram); cl_buffer_destroy(); } } void UTest::runAllNoIssue(void) { if (utestList == NULL) return; for (; retStatistics.finishrun < utestList->size(); ++retStatistics.finishrun) { const UTest &utest = (*utestList)[retStatistics.finishrun]; if (utest.fn == NULL || utest.haveIssue || utest.isBenchMark) continue; do_run(utest); cl_kernel_destroy(utest.needDestroyProgram); cl_buffer_destroy(); } } void UTest::runAllBenchMark(void) { if (utestList == NULL) return; for (; retStatistics.finishrun < utestList->size(); ++retStatistics.finishrun) { const UTest &utest = (*utestList)[retStatistics.finishrun]; if (utest.fn == NULL || utest.haveIssue || !utest.isBenchMark) continue; do_run(utest); cl_kernel_destroy(utest.needDestroyProgram); cl_buffer_destroy(); } } void UTest::listAllCases() { if (utestList == NULL) return; for (size_t i = 0; i < utestList->size(); ++i) { const UTest &utest = (*utestList)[i]; if (utest.fn == NULL) continue; std::cout << utest.name << std::endl; } } void UTest::listCasesCanRun() { if (utestList == NULL) return; for (size_t i = 0; i < utestList->size(); ++i) { const UTest &utest = (*utestList)[i]; if (utest.fn == NULL || utest.haveIssue || utest.isBenchMark) continue; std::cout << utest.name << std::endl; } } void UTest::listCasesWithIssue() { if (utestList == NULL) return; for (size_t i = 0; i < utestList->size(); ++i) { const UTest &utest = (*utestList)[i]; if (utest.fn == NULL || !utest.haveIssue || utest.isBenchMark) continue; std::cout << utest.name << std::endl; } }