test/harness/testcaseinput.c
changeset 15 c4b472e1fc9a
child 35 51a0beae92f6
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/test/harness/testcaseinput.c	Thu Feb 02 09:06:37 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 +}