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