13 GQuark testcase_error_quark(void)
15 return g_quark_from_static_string("testcase-error-quark");
20 * An insecure implementation of mkstemp(), for those platforms that
23 int mkstemp(char *template)
37 fd=open(s,O_RDWR|O_CREAT|O_EXCL,0600);
48 #endif /* !HAVE_MKSTEMP */
51 * As write(), but always convert NL to CR NL.
53 static size_t write_text(int fd,const char *buf,size_t count,GError **error)
61 if (_setmode(fd,_O_BINARY)<0)
64 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
65 "Failed to set mode of bookloupe input file to binary: %s",
74 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
75 "Failed to open stream to bookloupe input file: %s",
82 if (putc('\r',fp)==EOF)
84 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
85 "Error writing bookloupe input file: %s",g_strerror(errno));
89 if (putc(buf[i],fp)==EOF)
91 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
92 "Error writing bookloupe input file: %s",g_strerror(errno));
99 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
100 "Error writing bookloupe input file: %s",g_strerror(errno));
107 * Return the length (in bytes) or any common prefix between s1 and s2.
109 size_t common_prefix_length(const char *s1,const char *s2)
112 for(i=0;s1[i] && s2[i] && s1[i]==s2[i];i++)
117 void print_unexpected(const char *unexpected,gsize differs_at)
120 const char *endp,*bol;
122 endp=strchr(unexpected+differs_at,'\n');
124 endp=unexpected+strlen(unexpected);
125 string=g_string_new_len(unexpected,endp-unexpected);
126 bol=strrchr(string->str,'\n');
131 col=differs_at-(bol-string->str);
132 fprintf(stderr,"%s\n%*s^\n",string->str,col,"");
133 g_string_free(string,TRUE);
136 gboolean spawn_bootloupe(const char *encoding,const char *standard_input,
137 char **standard_output,char **filename,GError **error)
143 char input[]="TEST-XXXXXX";
146 GError *tmp_err=NULL;
151 s=g_convert(standard_input,-1,encoding,"UTF-8",NULL,&n,&tmp_err);
154 g_propagate_prefixed_error(error,tmp_err,
155 "Conversion to %s failed: ",encoding);
161 s=g_strdup(standard_input);
171 if (n && write_text(fd,s,n,error)!=n)
180 command[0]=getenv("BOOKLOUPE");
182 command[0]="." G_DIR_SEPARATOR_S "bookloupe";
187 r=spawn_sync(command,&s,&exit_status,error);
192 output=g_convert(s,-1,"UTF-8",encoding,NULL,NULL,&tmp_err);
196 g_propagate_prefixed_error(error,tmp_err,
197 "Conversion from %s failed: ",encoding);
204 if (!g_utf8_validate(s,-1,NULL))
206 g_set_error_literal(error,TESTCASE_ERROR,
207 TESTCASE_ERROR_FAILED,
208 "bookloupe output is not valid UTF-8");
216 r=spawn_sync(command,NULL,&exit_status,error);
220 if (r && exit_status)
222 g_set_error(error,TESTCASE_ERROR,TESTCASE_ERROR_FAILED,
223 "bookloupe exited with code %d",exit_status);
227 *filename=g_strdup(input);
228 if (r && standard_output)
229 *standard_output=output;
234 * Run a testcase, returning FALSE on fail or error and
235 * TRUE on pass or expected-fail.
236 * Suitable message(s) will be printed in all cases.
238 gboolean testcase_run(Testcase *testcase)
242 GString *header,*expected;
243 char *output,*filename,*s;
245 if (testcase->expected)
246 r=spawn_bootloupe(testcase->encoding,testcase->input,&output,&filename,
250 r=spawn_bootloupe(testcase->encoding,testcase->input,NULL,NULL,&error);
251 output=filename=NULL;
255 fprintf(stderr,"%s: FAIL\n",testcase->basename);
256 fprintf(stderr,"%s\n",error->message);
260 if (testcase->expected)
262 header=g_string_new("\n\nFile: ");
263 g_string_append(header,filename);
264 g_string_append(header,"\n");
265 expected=g_string_new(testcase->expected);
266 if (!g_str_has_prefix(output,header->str))
268 fprintf(stderr,"%s: FAIL\n",testcase->basename);
269 offset=common_prefix_length(output,header->str);
270 fprintf(stderr,"Unexpected header from bookloupe:\n");
271 print_unexpected(output,offset);
277 /* Skip the summary */
278 s=strstr(output+pos,"\n\n");
283 fprintf(stderr,"%s: FAIL\n",testcase->basename);
284 offset=common_prefix_length(output,header->str);
285 fprintf(stderr,"Unterminated summary from bookloupe:\n%s\n",
290 if (r && strcmp(output+pos,expected->str))
292 fprintf(stderr,"%s: FAIL\n",testcase->basename);
293 offset=common_prefix_length(output+pos,expected->str);
294 if (!offset && !output[pos+offset])
295 fprintf(stderr,"Unexpected zero warnings from bookloupe.\n");
298 fprintf(stderr,"Unexpected output from bookloupe:\n");
299 print_unexpected(output+pos,offset);
303 g_string_free(header,TRUE);
304 g_string_free(expected,TRUE);
309 fprintf(stderr,"%s: PASS\n",testcase->basename);
316 void testcase_free(Testcase *testcase)
318 g_free(testcase->basename);
319 g_free(testcase->input);
320 g_free(testcase->expected);
321 g_free(testcase->encoding);