1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/test/harness/testcaseinput.c Tue Feb 14 22:17:03 2012 +0000
1.3 @@ -0,0 +1,182 @@
1.4 +#include <stdlib.h>
1.5 +#include <stdio.h>
1.6 +#include <string.h>
1.7 +#include <unistd.h>
1.8 +#include <errno.h>
1.9 +#include <fcntl.h>
1.10 +#ifdef WIN32
1.11 +#include <io.h>
1.12 +#endif
1.13 +#include <glib.h>
1.14 +#include <glib/gstdio.h>
1.15 +#include <bl/bl.h>
1.16 +#include "testcase.h"
1.17 +#include "testcaseinput.h"
1.18 +
1.19 +#ifndef O_BINARY
1.20 +#define O_BINARY 0
1.21 +#endif
1.22 +
1.23 +/*
1.24 + * As write(), but with error handling.
1.25 + */
1.26 +static size_t write_file(int fd,const char *buf,size_t count,GError **error)
1.27 +{
1.28 + if (write(fd,buf,count)<count)
1.29 + {
1.30 + g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.31 + "Error writing bookloupe input file: %s",g_strerror(errno));
1.32 + return -1;
1.33 + }
1.34 + return count;
1.35 +}
1.36 +
1.37 +/*
1.38 + * Replace \n with \r\n and U+240A (visible symbol for LF) with \n
1.39 + */
1.40 +static char *unix2dos(const char *text)
1.41 +{
1.42 + gunichar c;
1.43 + const gunichar visible_lf=0x240A;
1.44 + GString *string;
1.45 + string=g_string_new(NULL);
1.46 + while(*text)
1.47 + {
1.48 + c=g_utf8_get_char(text);
1.49 + text=g_utf8_next_char(text);
1.50 + if (c=='\n')
1.51 + g_string_append(string,"\r\n");
1.52 + else if (c==visible_lf)
1.53 + g_string_append_c(string,'\n');
1.54 + else
1.55 + g_string_append_unichar(string,c);
1.56 + }
1.57 + return g_string_free(string,FALSE);
1.58 +}
1.59 +
1.60 +/*
1.61 + * Create an input file needed for a testcase (as specified in <input>).
1.62 + * The file is written in the encoding specified for communicating with
1.63 + * bookloupe. The name_used field of <input> is filled in with the name
1.64 + * of the created file (which may be different than the name specified
1.65 + * if that contained "XXXXXX" to be replaced by a unique string).
1.66 + */
1.67 +gboolean testcase_input_create(Testcase *testcase,TestcaseInput *input,
1.68 + GError **error)
1.69 +{
1.70 + int fd;
1.71 + size_t n;
1.72 + char *filename,*s,*t;
1.73 + GError *tmp_err=NULL;
1.74 + if (input->contents)
1.75 + {
1.76 + if (testcase->encoding)
1.77 + {
1.78 + t=unix2dos(input->contents);
1.79 + s=g_convert(t,-1,testcase->encoding,"UTF-8",NULL,&n,&tmp_err);
1.80 + g_free(t);
1.81 + if (!s)
1.82 + {
1.83 + g_propagate_prefixed_error(error,tmp_err,
1.84 + "Conversion to %s failed: ",testcase->encoding);
1.85 + return FALSE;
1.86 + }
1.87 + }
1.88 + else
1.89 + {
1.90 + s=unix2dos(input->contents);
1.91 + n=strlen(s);
1.92 + }
1.93 + }
1.94 + else
1.95 + {
1.96 + n=0;
1.97 + s=NULL;
1.98 + }
1.99 + g_free(input->name_used);
1.100 + input->name_used=NULL;
1.101 + if (testcase->tmpdir)
1.102 + filename=g_build_filename(testcase->tmpdir,input->name,NULL);
1.103 + else
1.104 + filename=g_strdup(input->name);
1.105 + if (strstr(input->name,"XXXXXX"))
1.106 + fd=g_mkstemp(filename);
1.107 + else
1.108 + fd=g_open(filename,O_WRONLY|O_CREAT|O_EXCL|O_BINARY,0600);
1.109 + if (fd<0)
1.110 + {
1.111 + g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.112 + "%s: %s",filename,g_strerror(errno));
1.113 + g_free(s);
1.114 + return FALSE;
1.115 + }
1.116 + input->name_used=g_strdup(filename+strlen(filename)-strlen(input->name));
1.117 + if (n && write_file(fd,s,n,error)!=n)
1.118 + {
1.119 + g_free(s);
1.120 + close(fd);
1.121 + (void)g_unlink(filename);
1.122 + g_free(filename);
1.123 + g_free(input->name_used);
1.124 + input->name_used=NULL;
1.125 + return FALSE;
1.126 + }
1.127 + g_free(s);
1.128 + if (close(fd)<0)
1.129 + {
1.130 + g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.131 + "%s: %s",filename,g_strerror(errno));
1.132 + (void)g_unlink(filename);
1.133 + g_free(filename);
1.134 + g_free(input->name_used);
1.135 + input->name_used=NULL;
1.136 + return FALSE;
1.137 + }
1.138 + g_free(filename);
1.139 + return TRUE;
1.140 +}
1.141 +
1.142 +/*
1.143 + * Remove an input file created with testcase_input_create()
1.144 + */
1.145 +gboolean testcase_input_remove(Testcase *testcase,TestcaseInput *input,
1.146 + GError **error)
1.147 +{
1.148 + char *filename;
1.149 + if (input->name_used)
1.150 + {
1.151 + if (testcase->tmpdir)
1.152 + filename=g_build_filename(testcase->tmpdir,input->name_used,NULL);
1.153 + else
1.154 + filename=g_strdup(input->name_used);
1.155 + if (g_unlink(filename)<0)
1.156 + {
1.157 + g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.158 + "%s: %s",filename,g_strerror(errno));
1.159 + return FALSE;
1.160 + }
1.161 + g_free(filename);
1.162 + g_free(input->name_used);
1.163 + input->name_used=NULL;
1.164 + }
1.165 + return TRUE;
1.166 +}
1.167 +
1.168 +/* Create a new description of an input file needed for a testcase */
1.169 +TestcaseInput *testcase_input_new(const char *name,const char *contents)
1.170 +{
1.171 + TestcaseInput *input;
1.172 + input=g_new0(TestcaseInput,1);
1.173 + input->name=g_strdup(name);
1.174 + input->contents=g_strdup(contents);
1.175 + return input;
1.176 +}
1.177 +
1.178 +/* Free the description of a testcase input file */
1.179 +void testcase_input_free(TestcaseInput *input)
1.180 +{
1.181 + g_free(input->name);
1.182 + g_free(input->name_used);
1.183 + g_free(input->contents);
1.184 + g_free(input);
1.185 +}