test/harness/testcaseinput.c
author ali <ali@juiblex.co.uk>
Mon Feb 06 23:55:27 2012 +0000 (2012-02-06)
changeset 17 2c88fd553e5d
child 35 51a0beae92f6
permissions -rw-r--r--
Add support for false-positives, etc.
     1 #include <stdlib.h>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <unistd.h>
     5 #include <errno.h>
     6 #include <fcntl.h>
     7 #ifdef WIN32
     8 #include <io.h>
     9 #endif
    10 #include <glib.h>
    11 #include <glib/gstdio.h>
    12 #include <bl/bl.h>
    13 #include "testcase.h"
    14 #include "testcaseinput.h"
    15 
    16 #ifndef O_BINARY
    17 #define O_BINARY 0
    18 #endif
    19 
    20 /*
    21  * As write(), but with error handling.
    22  */
    23 static size_t write_file(int fd,const char *buf,size_t count,GError **error)
    24 {
    25     if (write(fd,buf,count)<count)
    26     {
    27 	g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
    28 	  "Error writing bookloupe input file: %s",g_strerror(errno));
    29 	return -1;
    30     }
    31     return count;
    32 }
    33 
    34 /*
    35  * Replace \n with \r\n and U+240A (visible symbol for LF) with \n
    36  */
    37 static char *unix2dos(const char *text)
    38 {
    39     gunichar c;
    40     const gunichar visible_lf=0x240A;
    41     GString *string;
    42     string=g_string_new(NULL);
    43     while(*text)
    44     {
    45 	c=g_utf8_get_char(text);
    46 	text=g_utf8_next_char(text);
    47 	if (c=='\n')
    48 	    g_string_append(string,"\r\n");
    49 	else if (c==visible_lf)
    50 	    g_string_append_c(string,'\n');
    51 	else
    52 	    g_string_append_unichar(string,c);
    53     }
    54     return g_string_free(string,FALSE);
    55 }
    56 
    57 /*
    58  * Create an input file needed for a testcase (as specified in <input>).
    59  * The file is written in the encoding specified for communicating with
    60  * bookloupe. The name_used field of <input> is filled in with the name
    61  * of the created file (which may be different than the name specified
    62  * if that contained "XXXXXX" to be replaced by a unique string).
    63  */
    64 gboolean testcase_input_create(Testcase *testcase,TestcaseInput *input,
    65   GError **error)
    66 {
    67     int fd;
    68     size_t n;
    69     char *filename,*s,*t;
    70     GError *tmp_err=NULL;
    71     if (input->contents)
    72     {
    73 	if (testcase->encoding)
    74 	{
    75 	    t=unix2dos(input->contents);
    76 	    s=g_convert(t,-1,testcase->encoding,"UTF-8",NULL,&n,&tmp_err);
    77 	    g_free(t);
    78 	    if (!s)
    79 	    {
    80 		g_propagate_prefixed_error(error,tmp_err,
    81 		  "Conversion to %s failed: ",testcase->encoding);
    82 		return FALSE;
    83 	    }
    84 	}
    85 	else
    86 	{
    87 	    s=unix2dos(input->contents);
    88 	    n=strlen(s);
    89 	}
    90     }
    91     else
    92     {
    93 	n=0;
    94 	s=NULL;
    95     }
    96     g_free(input->name_used);
    97     input->name_used=NULL;
    98     if (testcase->tmpdir)
    99 	filename=g_build_filename(testcase->tmpdir,input->name,NULL);
   100     else
   101 	filename=g_strdup(input->name);
   102     if (strstr(input->name,"XXXXXX"))
   103 	fd=g_mkstemp(filename);
   104     else
   105 	fd=g_open(filename,O_WRONLY|O_CREAT|O_EXCL|O_BINARY,0600);
   106     if (fd<0)
   107     {
   108 	g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
   109 	  "%s: %s",filename,g_strerror(errno));
   110 	g_free(s);
   111 	return FALSE;
   112     }
   113     input->name_used=g_strdup(filename+strlen(filename)-strlen(input->name));
   114     if (n && write_file(fd,s,n,error)!=n)
   115     {
   116 	g_free(s);
   117 	close(fd);
   118 	(void)g_unlink(filename);
   119 	g_free(filename);
   120 	g_free(input->name_used);
   121 	input->name_used=NULL;
   122 	return FALSE;
   123     }
   124     g_free(s);
   125     if (close(fd)<0)
   126     {
   127 	g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
   128 	  "%s: %s",filename,g_strerror(errno));
   129 	(void)g_unlink(filename);
   130 	g_free(filename);
   131 	g_free(input->name_used);
   132 	input->name_used=NULL;
   133 	return FALSE;
   134     }
   135     g_free(filename);
   136     return TRUE;
   137 }
   138 
   139 /*
   140  * Remove an input file created with testcase_input_create()
   141  */
   142 gboolean testcase_input_remove(Testcase *testcase,TestcaseInput *input,
   143   GError **error)
   144 {
   145     char *filename;
   146     if (input->name_used)
   147     {
   148 	if (testcase->tmpdir)
   149 	    filename=g_build_filename(testcase->tmpdir,input->name_used,NULL);
   150 	else
   151 	    filename=g_strdup(input->name_used);
   152 	if (g_unlink(filename)<0)
   153 	{
   154 	    g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
   155 	      "%s: %s",filename,g_strerror(errno));
   156 	    return FALSE;
   157 	}
   158 	g_free(filename);
   159 	g_free(input->name_used);
   160 	input->name_used=NULL;
   161     }
   162     return TRUE;
   163 }
   164 
   165 /* Create a new description of an input file needed for a testcase */
   166 TestcaseInput *testcase_input_new(const char *name,const char *contents)
   167 {
   168     TestcaseInput *input;
   169     input=g_new0(TestcaseInput,1);
   170     input->name=g_strdup(name);
   171     input->contents=g_strdup(contents);
   172     return input;
   173 }
   174 
   175 /* Free the description of a testcase input file */
   176 void testcase_input_free(TestcaseInput *input)
   177 {
   178     g_free(input->name);
   179     g_free(input->name_used);
   180     g_free(input->contents);
   181     g_free(input);
   182 }