(file) Return to ut.cpp CVS log (file) (dir) Up to [OMI] / omi / ut

File: [OMI] / omi / ut / ut.cpp (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:39 2012 UTC (12 years, 1 month ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_1, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** 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 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

// StorageServiceTest.cpp : Defines the entry point for the console application.
//

#include "ut.h"
#include <vector>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>

#if defined(CONFIG_OS_WINDOWS)
# include <time.h>
#else
# include <unistd.h>
# include <sys/time.h>
# include <sys/types.h>
#endif

using namespace std;

namespace ut {
    typedef unsigned long long uint64;

    static vector< MODULE_TEST_CALLBACK > *s_fn;
    static int  s_tests = 0;
    static bool s_lastTestFailed = false;
    static vector< UnittestException > s_errors;
    static vector< string > s_warnings;
    static string s_TestsToRun;
    static unsigned int s_NumToRunEachTest = 1; // execute each test this number of times
    static bool s_printTestName = false;
    static const char*  s_argv0;
    static string s_xml_file;
    static uint64 s_test_start_time;
    static std::map<std::string, string> s_attributes;

    /* helper functions */
    static uint64 TimeNow()
    {
    #if defined(CONFIG_OS_WINDOWS)
        FILETIME ft;
        ULARGE_INTEGER tmp;

        GetSystemTimeAsFileTime(&ft);
        tmp.u.LowPart = ft.dwLowDateTime;
        tmp.u.HighPart = ft.dwHighDateTime;
        tmp.QuadPart -= 0X19DB1DED53E8000;
        return (tmp.QuadPart / (UINT64)10);
    #else
        struct timeval tv;
        struct timezone tz;
        memset(&tv, 0, sizeof(tv));
        memset(&tz, 0, sizeof(tz));

        if (gettimeofday(&tv, &tz) != 0)
            return 0;

        return ((uint64)tv.tv_sec * (uint64)1000000 + (uint64)tv.tv_usec);
    #endif
    }

    void registerCallback(MODULE_TEST_CALLBACK pfn)
    {
        if ( !s_fn )
            s_fn = new vector< MODULE_TEST_CALLBACK >;

        s_fn->push_back( pfn );
    }

    unsigned int testStarted(const char* name)
    {
        if ( !s_TestsToRun.empty() &&
            s_TestsToRun.find(string(",") + name + ",") == s_TestsToRun.npos )
            return 0;

        if (s_printTestName)
            cout << endl << name;

        s_tests++;
        s_test_start_time = TimeNow();

        return s_NumToRunEachTest;
    }

    void testCompleted(const char* /*name*/)
    {
        cout << (s_lastTestFailed ? "X" : "*");

        if (s_tests % 80 == 0)
            cout << endl;

        if (s_printTestName)
        {
            uint64 elapsed = TimeNow() - s_test_start_time;
            printf(" \t%d.%03d ms", 
                (int)(elapsed / 1000 ), //ms
                (int)(elapsed % 1000) ); // us

        }
        s_lastTestFailed = false;
    }

    void testFailed(const UnittestException& ex)
    {
        s_lastTestFailed = true;
        s_errors.push_back(ex);
    }

    void testWarning(const char* text)
    {
        s_warnings.push_back(text);
    }

    bool testGetAttr(const std::string& name, std::string& value)
    {
        map<string, string>::const_iterator it = s_attributes.find(name);

        if (it == s_attributes.end())
            return false;

        value = it->second;
        return true;
    }

};

using namespace ut;

static void Usage()
{
    printf("\
unit-test program; usage:\n\
\t%s [options] [tests-to-run]\n\
\t\tSupported options are:\n\
\t\t-h             - help screen\n\
\t\t-n <number>    - execute each test given number of times\n\
\t\t-p             - print out test name\n\
\t\t-xml <file>    - create xml results file\n\
\t\t-a <name>[=value] - set attribute for unittest\n\
\t\t<tests-to-run> - coma separated list of tests to run\n",
    s_argv0);
}

static void CheckArguments(int argc, char* argv[])
{
    for (int i = 0; i < argc; )
    {
        /* Check for -I option */
        if (strcmp(argv[i], "-n") == 0)
        {
            /* Check for mandatory option argument */
            if (i + 1 == argc)
            {
                fprintf(stderr, "Missing option argument for -n");
                Usage();
                exit(1);
            }

            /* Append path to array */
            s_NumToRunEachTest = atol(argv[i+1]);

            /* Remove option and its argument from argv */
            memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
            argc -= 2;
        }
        else if (strcmp(argv[i], "-xml") == 0)
        {
            /* Check for mandatory option argument */
            if (i + 1 == argc)
            {
                fprintf(stderr, "Missing option argument for -xml");
                Usage();
                exit(1);
            }

            /* Append path to array */
            s_xml_file = argv[i+1];

            /* Remove option and its argument from argv */
            memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
            argc -= 2;
        }
        else if (strcmp(argv[i], "-p") == 0)
        {
            s_printTestName = true;

            /* Remove option and its argument from argv */
            memmove(&argv[i], &argv[i+1], sizeof(char*) * (argc-i-1));
            argc--;
        }
        else if (strcmp(argv[i], "-a") == 0)
        {
            /* Check for mandatory option argument */
            if (i + 1 == argc)
            {
                fprintf(stderr, "Missing option argument for -a");
                Usage();
                exit(1);
            }

            /* Append path to array */
            {
                const char* name = argv[i+1];
                const char* value = strchr(name, '=');

                string strName, strValue;

                if (value)
                {
                    strName = string(name, value);
                    strValue = value+1;
                }
                else
                {
                    strName = name;
                }
                //s_attributes[ strName ] = strValue;
                s_attributes.insert(pair<string, string>(strName, strValue));

            }

            /* Remove option and its argument from argv */
            memmove(&argv[i], &argv[i+2], sizeof(char*) * (argc-i-2));
            argc -= 2;
        }
        else if (strcmp(argv[i], "-h") == 0)
        {
            Usage();
            exit(0);
        }
        else if (argv[i][0] == '-')
        {
            fprintf(stderr, "unknown option: %s", argv[i]);
            Usage();
            exit(1);
        }
        else
            i++;
    }

    if ( argc > 1 )
    {
        s_TestsToRun = string(",") + argv[1] + ",";
    }

}

static void produceXmlOutput()
{
    // create xml from results
//<?xml version="1.0" encoding='ISO-8859-1' standalone='yes' ?>
//<?xml-stylesheet type="text/xsl" href="report.xsl"?>
//<Statistics>
//  <Tests>687</Tests>
//  <FailuresTotal>0</FailuresTotal>
//  <Errors>0</Errors>
//  <Failures>0</Failures>
//</Statistics>
    try 
    {
        ofstream fst( s_xml_file.c_str(), ios_base::out);

        fst << "\
<?xml version=\"1.0\" encoding='ISO-8859-1' standalone='yes' ?>\
<Statistics>\
  <Tests>" << s_tests << "</Tests>\
<FailuresTotal>" << s_errors.size() << "</FailuresTotal>\
<Errors>0</Errors>\
<Failures>0</Failures>\
</Statistics>";

        if ( fst.bad() )
            throw 1;
    }
    catch(...)
    {
        cerr << "unable to open file " << s_xml_file << endl;
    }

}

int main(int argc, char* argv[])
{
    s_argv0 = argv[0];

    if ( !s_fn )
    {
        cout << "no tests to run..." << endl;
        return 0;
    }

    CheckArguments(argc,argv);

    uint64 starttime = TimeNow();

    for ( unsigned int i = 0; i < s_fn->size(); i++ )
    {
        (*s_fn)[i] ();
    }

    cout << endl << endl 
        << "completed " << s_tests << " test" << (s_tests != 1 ? "s" : "" )
        << "; ";

    if ( s_errors.empty() )
        cout << "OK" << endl;
    else
        cout << s_errors.size() << " FAILED" << endl << endl;

    uint64 elapsed = TimeNow() - starttime;
    printf(" \tspent %d.%03d ms\n\n", 
        (int)(elapsed / 1000 ), //ms
        (int)(elapsed % 1000) ); // us

    for ( unsigned int i = 0; i < s_errors.size(); i++ )
    {

        cout << "test-case: " << s_errors[i].m_testcase << endl;
        cout << "function: " << s_errors[i].m_function << endl;
        cout << "file: " << s_errors[i].m_file << ":" << s_errors[i].m_line << endl;
        cout << "condition: " << s_errors[i].m_text << endl << endl;
    }

    if (!s_warnings.empty())
    {
        cout << endl << "Warnings:" << endl;

        for ( unsigned int i = 0; i < s_warnings.size(); i++ )
        {

            cout << s_warnings[i] << endl;
        }
        cout << endl;

    }

    if ( !s_xml_file.empty())
    {
        produceXmlOutput();
    }

    delete s_fn; s_fn = 0;

    return s_errors.empty() ? 0 : 1;
}

void __UT_TEST(
    const char* testName, 
    void (*setUp)(), 
    void (*cleanUp)(), 
    void (*test)())
{
    bool setup_called = false;
    unsigned int num = ut::testStarted(testName);

    for(unsigned int counter = 0; counter < num; counter++)
    {
	try 
	{
	    setUp();
	    setup_called = true;
	}
	catch (ut::UnittestException ex)
	{
	    ex.m_testcase = string(testName) + " --setup--";
	    testFailed(ex);
	}

	if (setup_called) 
	{
	    try 
	    {
		test();
	    } 
	    catch (ut::UnittestException ex)
	    {
		ex.m_testcase = testName; 
		testFailed(ex);
	    }
	}

	if (setup_called) 
	{
	    try 
	    {
		cleanUp();
	    } 
	    catch (ut::UnittestException ex)
	    {
		ex.m_testcase = string(testName) + "  --cleanup--"; 
		testFailed(ex);
	    }
	}

	ut::testCompleted(testName);
    }
}

ViewCVS 0.9.2