9 GQuark testcase_error_quark(void)
11 return g_quark_from_static_string("testcase-error-quark");
15 * As write(), but with error handling.
17 static size_t write_file(int fd,const char *buf,size_t count,GError **error)
19 if (write(fd,buf,count)<count)
21 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
22 "Error writing bookloupe input file: %s",g_strerror(errno));
29 * Return the length (in bytes) of any common prefix between s1 and s2.
30 * The returned length will always represent an exact number of characters.
32 size_t common_prefix_length(const char *s1,const char *s2)
38 c1=g_utf8_get_char(s1);
39 c2=g_utf8_get_char(s2);
42 s1=g_utf8_next_char(s1);
43 s2=g_utf8_next_char(s2);
48 void print_unexpected(const char *unexpected,gsize differs_at)
52 const char *endp,*bol,*s;
54 endp=strchr(unexpected+differs_at,'\n');
56 endp=unexpected+strlen(unexpected);
57 string=g_string_new_len(unexpected,endp-unexpected);
58 bol=strrchr(string->str,'\n');
65 endp=string->str+differs_at;
69 s=g_utf8_next_char(s);
72 else if (g_unichar_iswide(c))
74 else if (!g_unichar_iszerowidth(c))
77 fprintf(stderr,"%s\n%*s^\n",string->str,col,"");
78 g_string_free(string,TRUE);
82 * Replace \n with \r\n and U+240A (visible symbol for LF) with \n
84 char *unix2dos(const char *text)
87 const gunichar visible_lf=0x240A;
89 string=g_string_new(NULL);
92 c=g_utf8_get_char(text);
93 text=g_utf8_next_char(text);
95 g_string_append(string,"\r\n");
96 else if (c==visible_lf)
97 g_string_append_c(string,'\n');
99 g_string_append_unichar(string,c);
101 return g_string_free(string,FALSE);
104 gboolean spawn_bootloupe(const char *encoding,const char *standard_input,
105 char **standard_output,char **filename,GError **error)
110 char input[]="TEST-XXXXXX";
113 GError *tmp_err=NULL;
118 t=unix2dos(standard_input);
119 s=g_convert(t,-1,encoding,"UTF-8",NULL,&n,&tmp_err);
123 g_propagate_prefixed_error(error,tmp_err,
124 "Conversion to %s failed: ",encoding);
130 s=unix2dos(standard_input);
140 if (n && write_file(fd,s,n,error)!=n)
149 command[0]=getenv("BOOKLOUPE");
151 command[0]="." G_DIR_SEPARATOR_S "bookloupe";
156 r=spawn_sync(command,&s,&exit_status,error);
161 output=g_convert(s,-1,"UTF-8",encoding,NULL,NULL,&tmp_err);
165 g_propagate_prefixed_error(error,tmp_err,
166 "Conversion from %s failed: ",encoding);
173 if (!g_utf8_validate(s,-1,NULL))
175 g_set_error_literal(error,TESTCASE_ERROR,
176 TESTCASE_ERROR_FAILED,
177 "bookloupe output is not valid UTF-8");
185 r=spawn_sync(command,NULL,&exit_status,error);
189 if (r && exit_status)
191 g_set_error(error,TESTCASE_ERROR,TESTCASE_ERROR_FAILED,
192 "bookloupe exited with code %d",exit_status);
196 *filename=g_strdup(input);
197 if (r && standard_output)
198 *standard_output=output;
203 * Run a testcase, returning FALSE on fail or error and
204 * TRUE on pass or expected-fail.
205 * Suitable message(s) will be printed in all cases.
207 gboolean testcase_run(Testcase *testcase)
211 GString *header,*expected;
212 char *output,*filename,*s;
214 if (testcase->expected)
215 r=spawn_bootloupe(testcase->encoding,testcase->input,&output,&filename,
219 r=spawn_bootloupe(testcase->encoding,testcase->input,NULL,NULL,&error);
220 output=filename=NULL;
224 fprintf(stderr,"%s: FAIL\n",testcase->basename);
225 fprintf(stderr,"%s\n",error->message);
229 if (testcase->expected)
231 header=g_string_new("\n\nFile: ");
232 g_string_append(header,filename);
233 g_string_append(header,"\n");
234 expected=g_string_new(testcase->expected);
235 if (!g_str_has_prefix(output,header->str))
237 fprintf(stderr,"%s: FAIL\n",testcase->basename);
238 offset=common_prefix_length(output,header->str);
239 fprintf(stderr,"Unexpected header from bookloupe:\n");
240 print_unexpected(output,offset);
246 /* Skip the summary */
247 s=strstr(output+pos,"\n\n");
252 fprintf(stderr,"%s: FAIL\n",testcase->basename);
253 offset=common_prefix_length(output,header->str);
254 fprintf(stderr,"Unterminated summary from bookloupe:\n%s\n",
259 if (r && strcmp(output+pos,expected->str))
261 fprintf(stderr,"%s: FAIL\n",testcase->basename);
262 offset=common_prefix_length(output+pos,expected->str);
263 if (!offset && !output[pos+offset])
264 fprintf(stderr,"Unexpected zero warnings from bookloupe.\n");
267 fprintf(stderr,"Unexpected output from bookloupe:\n");
268 print_unexpected(output+pos,offset);
272 g_string_free(header,TRUE);
273 g_string_free(expected,TRUE);
278 fprintf(stderr,"%s: PASS\n",testcase->basename);
285 void testcase_free(Testcase *testcase)
287 g_free(testcase->basename);
288 g_free(testcase->input);
289 g_free(testcase->expected);
290 g_free(testcase->encoding);