Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Very early version of module that creates XML-based test reports.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkauppila committed Jun 19, 2011
1 parent e0d9ee8 commit afe1c4a
Show file tree
Hide file tree
Showing 2 changed files with 377 additions and 0 deletions.
43 changes: 43 additions & 0 deletions test/test-automation/logger.h
@@ -0,0 +1,43 @@
/*
Copyright (C) 2011 Markus Kauppila <markus.kauppila@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#ifndef _LOGGER_H
#define _LOGGER_H

/*!
* Init the logger.
*/
//int LogInit();

/*!
* Quit the logger.
*/
//int LogQuit();

/*!
* Generic ouput function for the logger. Prints the
* message to stderr.
*
* \param scope Source of message (eg. suite, test, harness)
* \return non-zero if logging fails, zero on success
*/
//int LogGenericOutput(int scope, const char *message, ...);

#endif
334 changes: 334 additions & 0 deletions test/test-automation/xml_logger.c
@@ -0,0 +1,334 @@
/*
Copyright (C) 2011 Markus Kauppila <markus.kauppila@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#ifndef _LOGGER_C
#define _LOGGER_C

#include "logger.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

/* \todo
* - Fp to LogGenericOutput
* - print <?xml version="1.0" encoding="utf-8" ?> as header
* - use SDL_malloc etc...
* - nest output /OK
* - dummy functions for no-xml execution
* - Make XML (and relevant comparisions) case-insensitive
*/


/*! Function pointer definitions. \todo Move to logger.h */
typedef int (*LogInitFp)(void);
typedef int (*LogCleanUptFp)(void);

/*! Function prototypes */
int LogGenericOutput(char *message);
int XMLLogOutput(const char *tag, const char *fmt, va_list list);

static int xml_enabled = 1;

static int loggingPriority = 0;
static int nestingDepth = 0;

enum Priority {
VERBOSE,
DEFAULT,
SILENT
};


#define TAG_START 0x00000001
#define TAG_END 0x00000002
#define TAG_BOTH (TAG_START & TAG_END)

/*!
* Defines structure used for "counting" open XML-tags
*/
typedef struct TagList {
const char *tag;
struct TagList *next;
} TagList;

static TagList *openTags = NULL;

/*!
* Prepend the open tags list
*/
static int
AddOpenTag(const char *tag)
{
TagList *openTag = malloc(sizeof(TagList));
if(openTag == NULL) {
return 1;
}
memset(openTag, 0, sizeof(TagList));

openTag->tag = tag; // Should be fine without malloc?
openTag->next = openTags;

openTags = openTag;

return 0;
}

/*!
* Removes the first tag from the open tag list
*/
static int
RemoveOpenTag(const char *tag)
{
if(openTags == NULL) {
return 1;
}

int retVal = 0;

// Tag should always be the same as previously opened tag
// to prevent opening and ending tag mismatch
if(strcmp(openTags->tag, tag) == 0) {
TagList *openTag = openTags;
openTags = openTags->next;

free(openTag);
} else {
printf("Else activated!");
retVal = 1;
}

return retVal;
}

/*!
* Goes through the open tag list and checks if
* given tag is already opened
*
* \return 1 is tag is open, 0 if not
*/
static int
IsTagOpen(const char *tag)
{
int retVal = 0;

TagList *openTag = NULL;
for(openTag = openTags; openTag; openTag = openTag->next) {
if(strcmp(openTag->tag, tag) == 0) {
retVal = 1;
break;
}
}

return retVal;
}

/*!
* Debug function. Prints the contents of the open tags list.
*/
static int
PrintOpenTags()
{
printf("\nOpen tags:\n");

TagList *openTag = NULL;
for(openTag = openTags; openTag; openTag = openTag->next) {
printf("\ttag: %s\n", openTag->tag);
}
}

//! \TODO move these to upwards!!
int XMLStartTag(int priority, const char *tag);
int XMLEndTag(int priority, const char *tag);

int
XMLLogInit()
{

LogGenericOutput("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");

XMLStartTag(0, "testlog");
}

int
XMLLogCleanUp()
{
//! \todo do CloseOpenTags() instead
XMLEndTag(0, "testlog");
}

/*!
* Forms a valid XML-tag based on the given parameters
*
* \param tag XML-tag to create
* \param tagStyle Do start or end tag, or both.
* \param message text content of the tags
*/
static char *
Tagify(const char *tag, const int tagStyle, const char *message)
{
// buffer simplifies the creation of the string
const int bufferSize = 1024;
char buffer[bufferSize];
memset(buffer, 0, bufferSize);

if(tagStyle & TAG_START) {
strcat(buffer, "<");
strcat(buffer, tag);
strcat(buffer, ">");
}

if(message) {
strcat(buffer, message);
}

if(tagStyle & TAG_END) {
strcat(buffer, "</");
strcat(buffer, tag);
strcat(buffer, ">");
}


const int size = strlen(buffer) + 1;
char *newTag = malloc(size * sizeof(char));
memset(newTag, 0, size * sizeof(char));
memcpy(newTag, buffer, size);

return newTag;
}


int
XMLStartTag(int priority, const char *tag)
{
if(priority < loggingPriority) {
return 1;
}

AddOpenTag(tag);
char *newTag = Tagify(tag, TAG_START, NULL);
LogGenericOutput(newTag);
free(newTag);

nestingDepth++;
}

int
XMLEndTag(int priority, const char *tag)
{
/*
Do it before priority check, so incorrect usage of
priorities won't mess it up
*/
nestingDepth--;

if(priority < loggingPriority) {
return 1;
}

RemoveOpenTag(tag);

char *newTag = Tagify(tag, TAG_END, NULL);
LogGenericOutput(newTag);
free(newTag);
}

int
XMLTag(int priority, const char *tag, const char *fmt, ...)
{
if(priority < loggingPriority) {
return 1;
}

const int bufferSize = 1024;
char buffer[bufferSize];
memset(buffer, 0, bufferSize);

va_list list;
va_start(list, fmt);
vsnprintf(buffer, bufferSize, fmt, list);
va_end(list);

char *newTag = Tagify(tag, TAG_BOTH, buffer);
LogGenericOutput(newTag);
free(newTag);
}

//! \TODO Make it changeable by using a function pointer
/*!
* Prints the given message to stderr. Function adds nesting
* to the output.
*/
int
LogGenericOutput(char *message)
{
int depth = nestingDepth;
while(depth--) {
fprintf(stderr, " ");
}

fprintf(stderr, "%s\n", message);
}


/*!
* Main for testing the logger
*/
int
main()
{
LogInitFp LogInit = NULL;
LogCleanUptFp LogCleanUp = NULL;

if(xml_enabled) {
// set logger functions to XML
LogInit = XMLLogInit;
LogCleanUp = XMLLogCleanUp;
} else {
// set up dummy functions
}

LogInit();
XMLStartTag(0, "hello");
XMLStartTag(0, "world!");
XMLEndTag(0, "world!");
XMLEndTag(0, "hello");

LogCleanUp();



#if 0
XMLStartTag("log");
XMLStartTag("suite");
XMLStartTag("test");

XMLEndTag("test");
XMLEndTag("suite");


PrintOpenTags();
#endif

return 0;
}

#endif

0 comments on commit afe1c4a

Please sign in to comment.