1.1 --- a/Makefile.am Sat Oct 26 18:47:33 2013 +0100
1.2 +++ b/Makefile.am Fri Oct 25 11:15:18 2013 +0100
1.3 @@ -1,1 +1,3 @@
1.4 SUBDIRS=bl bookloupe test doc
1.5 +
1.6 +dist_pkgdata_DATA=sample.ini
2.1 --- a/bookloupe/bookloupe.c Sat Oct 26 18:47:33 2013 +0100
2.2 +++ b/bookloupe/bookloupe.c Fri Oct 25 11:15:18 2013 +0100
2.3 @@ -128,35 +128,97 @@
2.4
2.5 gboolean pswit[SWITNO]; /* program switches */
2.6
2.7 +gboolean typo_compat,paranoid_compat;
2.8 +
2.9 static GOptionEntry options[]={
2.10 { "dp", 'd', 0, G_OPTION_ARG_NONE, pswit+DP_SWITCH,
2.11 "Ignore DP-specific markup", NULL },
2.12 - { "noecho", 'e', 0, G_OPTION_ARG_NONE, pswit+ECHO_SWITCH,
2.13 + { "no-dp", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.14 + G_OPTION_ARG_NONE, pswit+DP_SWITCH,
2.15 + "Don't ignore DP-specific markup", NULL },
2.16 + { "echo", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, pswit+ECHO_SWITCH,
2.17 + "Echo queried line", NULL },
2.18 + { "no-echo", 'e', G_OPTION_FLAG_REVERSE,
2.19 + G_OPTION_ARG_NONE, pswit+ECHO_SWITCH,
2.20 "Don't echo queried line", NULL },
2.21 { "squote", 's', 0, G_OPTION_ARG_NONE, pswit+SQUOTE_SWITCH,
2.22 "Check single quotes", NULL },
2.23 - { "typo", 't', 0, G_OPTION_ARG_NONE, pswit+TYPO_SWITCH,
2.24 + { "no-squote", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.25 + G_OPTION_ARG_NONE, pswit+SQUOTE_SWITCH,
2.26 + "Don't check single quotes", NULL },
2.27 + { "typo", 0, 0, G_OPTION_ARG_NONE, pswit+TYPO_SWITCH,
2.28 "Check common typos", NULL },
2.29 + { "no-typo", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.30 + G_OPTION_ARG_NONE, pswit+TYPO_SWITCH,
2.31 + "Don't check common typos", NULL },
2.32 { "qpara", 'p', 0, G_OPTION_ARG_NONE, pswit+QPARA_SWITCH,
2.33 "Require closure of quotes on every paragraph", NULL },
2.34 - { "relaxed", 'x', 0, G_OPTION_ARG_NONE, pswit+PARANOID_SWITCH,
2.35 + { "no-qpara", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.36 + G_OPTION_ARG_NONE, pswit+QPARA_SWITCH,
2.37 + "Don't require closure of quotes on every paragraph", NULL },
2.38 + { "paranoid", 0, G_OPTION_FLAG_HIDDEN,
2.39 + G_OPTION_ARG_NONE, pswit+PARANOID_SWITCH,
2.40 + "Enable paranoid querying of everything", NULL },
2.41 + { "no-paranoid", 0, G_OPTION_FLAG_REVERSE,
2.42 + G_OPTION_ARG_NONE, pswit+PARANOID_SWITCH,
2.43 "Disable paranoid querying of everything", NULL },
2.44 - { "line-end", 'l', 0, G_OPTION_ARG_NONE, pswit+LINE_END_SWITCH,
2.45 + { "line-end", 0, G_OPTION_FLAG_HIDDEN,
2.46 + G_OPTION_ARG_NONE, pswit+LINE_END_SWITCH,
2.47 + "Enable line end checking", NULL },
2.48 + { "no-line-end", 'l', G_OPTION_FLAG_REVERSE,
2.49 + G_OPTION_ARG_NONE, pswit+LINE_END_SWITCH,
2.50 "Disable line end checking", NULL },
2.51 { "overview", 'o', 0, G_OPTION_ARG_NONE, pswit+OVERVIEW_SWITCH,
2.52 "Overview: just show counts", NULL },
2.53 + { "no-overview", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.54 + G_OPTION_ARG_NONE, pswit+OVERVIEW_SWITCH,
2.55 + "Show individual warnings", NULL },
2.56 { "stdout", 'y', 0, G_OPTION_ARG_NONE, pswit+STDOUT_SWITCH,
2.57 "Output errors to stdout instead of stderr", NULL },
2.58 + { "no-stdout", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.59 + G_OPTION_ARG_NONE, pswit+STDOUT_SWITCH,
2.60 + "Output errors to stderr instead of stdout", NULL },
2.61 { "header", 'h', 0, G_OPTION_ARG_NONE, pswit+HEADER_SWITCH,
2.62 "Echo header fields", NULL },
2.63 + { "no-header", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.64 + G_OPTION_ARG_NONE, pswit+HEADER_SWITCH,
2.65 + "Don't echo header fields", NULL },
2.66 { "markup", 'm', 0, G_OPTION_ARG_NONE, pswit+MARKUP_SWITCH,
2.67 "Ignore markup in < >", NULL },
2.68 + { "no-markup", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.69 + G_OPTION_ARG_NONE, pswit+MARKUP_SWITCH,
2.70 + "No special handling for markup in < >", NULL },
2.71 { "usertypo", 'u', 0, G_OPTION_ARG_NONE, pswit+USERTYPO_SWITCH,
2.72 "Use file of user-defined typos", NULL },
2.73 + { "no-usertypo", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.74 + G_OPTION_ARG_NONE, pswit+USERTYPO_SWITCH,
2.75 + "Ignore file of user-defined typos", NULL },
2.76 + { "verbose", 'v', 0, G_OPTION_ARG_NONE, pswit+VERBOSE_SWITCH,
2.77 + "Verbose - list everything", NULL },
2.78 + { "no-verbose", 0, G_OPTION_FLAG_HIDDEN|G_OPTION_FLAG_REVERSE,
2.79 + G_OPTION_ARG_NONE, pswit+VERBOSE_SWITCH,
2.80 + "Switch off verbose mode", NULL },
2.81 + { NULL }
2.82 +};
2.83 +
2.84 +/*
2.85 + * Options relating to configuration which make no sense from inside
2.86 + * a configuration file.
2.87 + */
2.88 +
2.89 +static GOptionEntry config_options[]={
2.90 { "web", 'w', 0, G_OPTION_ARG_NONE, pswit+WEB_SWITCH,
2.91 "Defaults for use on www upload", NULL },
2.92 - { "verbose", 'v', 0, G_OPTION_ARG_NONE, pswit+VERBOSE_SWITCH,
2.93 - "Verbose - list everything", NULL },
2.94 + { "dump-config", 0, 0, G_OPTION_ARG_NONE, pswit+DUMP_CONFIG_SWITCH,
2.95 + "Dump current config settings", NULL },
2.96 + { NULL }
2.97 +};
2.98 +
2.99 +static GOptionEntry compatibility_options[]={
2.100 + { "toggle-typo", 't', 0, G_OPTION_ARG_NONE, &typo_compat,
2.101 + "Toggle checking for common typos", NULL },
2.102 + { "toggle-relaxed", 'x', 0, G_OPTION_ARG_NONE, ¶noid_compat,
2.103 + "Toggle both paranoid mode and common typos", NULL },
2.104 { NULL }
2.105 };
2.106
2.107 @@ -200,31 +262,198 @@
2.108 UINT saved_cp;
2.109 #endif
2.110
2.111 +GKeyFile *config;
2.112 +
2.113 +void config_file_update(GKeyFile *kf)
2.114 +{
2.115 + int i;
2.116 + gboolean sw;
2.117 + for(i=0;options[i].long_name;i++)
2.118 + {
2.119 + if (g_str_has_prefix(options[i].long_name,"no-"))
2.120 + continue;
2.121 + if (options[i].arg==G_OPTION_ARG_NONE)
2.122 + {
2.123 + sw=*(gboolean *)options[i].arg_data;
2.124 + if (options[i].flags&G_OPTION_FLAG_REVERSE)
2.125 + sw=!sw;
2.126 + g_key_file_set_boolean(kf,"options",options[i].long_name,sw);
2.127 + }
2.128 + else
2.129 + g_assert_not_reached();
2.130 + }
2.131 +}
2.132 +
2.133 +void config_file_add_comments(GKeyFile *kf)
2.134 +{
2.135 + int i;
2.136 + gchar *comment;
2.137 + g_key_file_set_comment(kf,NULL,NULL," Default configuration for bookloupe",
2.138 + NULL);
2.139 + for(i=0;options[i].long_name;i++)
2.140 + {
2.141 + if (g_str_has_prefix(options[i].long_name,"no-"))
2.142 + continue;
2.143 + comment=g_strconcat(" ",options[i].description,NULL);
2.144 + g_key_file_set_comment(kf,"options",options[i].long_name,comment,NULL);
2.145 + g_free(comment);
2.146 + }
2.147 +}
2.148 +
2.149 +void dump_config(void)
2.150 +{
2.151 + gchar *s;
2.152 + if (config)
2.153 + config_file_update(config);
2.154 + else
2.155 + {
2.156 + config=g_key_file_new();
2.157 + config_file_update(config);
2.158 + config_file_add_comments(config);
2.159 + }
2.160 + s=g_key_file_to_data(config,NULL,NULL);
2.161 + if (s)
2.162 + g_print("%s",s);
2.163 + g_free(s);
2.164 +}
2.165 +
2.166 +GKeyFile *read_config_file(gchar **full_path)
2.167 +{
2.168 + int i;
2.169 + GError *err=NULL;
2.170 + gchar **search_dirs;
2.171 + gchar *path;
2.172 + const char *search_path;
2.173 + GKeyFile *kf;
2.174 + kf=g_key_file_new();
2.175 + search_path=g_getenv("BOOKLOUPE_CONFIG_PATH");
2.176 + if (search_path)
2.177 + {
2.178 +#ifdef __WIN32__
2.179 + search_dirs=g_strsplit(search_path,";",0);
2.180 +#else
2.181 + search_dirs=g_strsplit(search_path,":",0);
2.182 +#endif
2.183 + }
2.184 + else
2.185 + {
2.186 + search_dirs=g_new(gchar *,4);
2.187 + search_dirs[0]=g_get_current_dir();
2.188 + search_dirs[1]=g_strdup(running_from);
2.189 + search_dirs[2]=g_strdup(g_get_user_config_dir());
2.190 + search_dirs[3]=NULL;
2.191 + }
2.192 + for(i=0;search_dirs[i];i++)
2.193 + {
2.194 + path=g_build_filename(search_dirs[i],"bookloupe.ini",NULL);
2.195 + if (g_key_file_load_from_file(kf,path,
2.196 + G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,&err))
2.197 + break;
2.198 + if (!g_error_matches(err,G_FILE_ERROR,G_FILE_ERROR_NOENT))
2.199 + {
2.200 + g_printerr("Bookloupe: Error reading %s\n",path);
2.201 + g_printerr("%s\n",err->message);
2.202 + exit(1);
2.203 + }
2.204 + g_clear_error(&err);
2.205 + g_free(path);
2.206 + path=NULL;
2.207 + }
2.208 + if (!search_dirs[i])
2.209 + {
2.210 + g_key_file_free(kf);
2.211 + kf=NULL;
2.212 + }
2.213 + g_strfreev(search_dirs);
2.214 + if (full_path && kf)
2.215 + *full_path=path;
2.216 + else
2.217 + g_free(path);
2.218 + return kf;
2.219 +}
2.220 +
2.221 +void parse_config_file(void)
2.222 +{
2.223 + int i,j;
2.224 + gchar *path;
2.225 + gchar **keys;
2.226 + gboolean sw;
2.227 + GError *err=NULL;
2.228 + config=read_config_file(&path);
2.229 + if (config)
2.230 + keys=g_key_file_get_keys(config,"options",NULL,NULL);
2.231 + else
2.232 + keys=NULL;
2.233 + if (keys)
2.234 + {
2.235 + for(i=0;keys[i];i++)
2.236 + {
2.237 + for(j=0;options[j].long_name;j++)
2.238 + {
2.239 + if (g_str_has_prefix(options[j].long_name,"no-"))
2.240 + continue;
2.241 + else if (!strcmp(keys[i],options[j].long_name))
2.242 + {
2.243 + if (options[j].arg==G_OPTION_ARG_NONE)
2.244 + {
2.245 + sw=g_key_file_get_boolean(config,"options",keys[i],
2.246 + &err);
2.247 + if (err)
2.248 + {
2.249 + g_printerr("Bookloupe: %s: options.%s: %s\n",
2.250 + path,keys[i],err->message);
2.251 + g_clear_error(&err);
2.252 + }
2.253 + if (options[j].flags&G_OPTION_FLAG_REVERSE)
2.254 + sw=!sw;
2.255 + *(gboolean *)options[j].arg_data=sw;
2.256 + break;
2.257 + }
2.258 + else
2.259 + g_assert_not_reached();
2.260 + }
2.261 + }
2.262 + if (!options[j].long_name)
2.263 + g_printerr("Bookloupe: %s: Unknown option \"%s\" ignored\n",
2.264 + path,keys[i]);
2.265 + }
2.266 + g_strfreev(keys);
2.267 + }
2.268 + if (config)
2.269 + g_free(path);
2.270 +}
2.271 +
2.272 void parse_options(int *argc,char ***argv)
2.273 {
2.274 GError *err=NULL;
2.275 GOptionContext *context;
2.276 + GOptionGroup *compatibility;
2.277 context=g_option_context_new(
2.278 - "file - looks for errors in Project Gutenberg(TM) etexts");
2.279 + "file - look for errors in Project Gutenberg(TM) etexts");
2.280 g_option_context_add_main_entries(context,options,NULL);
2.281 + g_option_context_add_main_entries(context,config_options,NULL);
2.282 + compatibility=g_option_group_new("compatibility",
2.283 + "Options for Compatibility with Gutcheck:",
2.284 + "Show compatibility options",NULL,NULL);
2.285 + g_option_group_add_entries(compatibility,compatibility_options);
2.286 + g_option_context_add_group(context,compatibility);
2.287 + g_option_context_set_description(context,
2.288 + "For simplicity, only the switch options which reverse the\n"
2.289 + "default configuration are listed. In most cases, both vanilla\n"
2.290 + "and \"no-\" prefixed versions are available for use.");
2.291 if (!g_option_context_parse(context,argc,argv,&err))
2.292 {
2.293 g_printerr("Bookloupe: %s\n",err->message);
2.294 g_printerr("Use \"%s --help\" for help\n",(*argv)[0]);
2.295 exit(1);
2.296 }
2.297 - /* Paranoid checking is turned OFF, not on, by its switch */
2.298 - pswit[PARANOID_SWITCH]=!pswit[PARANOID_SWITCH];
2.299 - if (pswit[PARANOID_SWITCH])
2.300 - /* if running in paranoid mode, typo checks default to enabled */
2.301 + if (typo_compat)
2.302 pswit[TYPO_SWITCH]=!pswit[TYPO_SWITCH];
2.303 - /* Line-end checking is turned OFF, not on, by its switch */
2.304 - pswit[LINE_END_SWITCH]=!pswit[LINE_END_SWITCH];
2.305 - /* Echoing is turned OFF, not on, by its switch */
2.306 - pswit[ECHO_SWITCH]=!pswit[ECHO_SWITCH];
2.307 - if (pswit[OVERVIEW_SWITCH])
2.308 - /* just print summary; don't echo */
2.309 - pswit[ECHO_SWITCH]=FALSE;
2.310 + if (paranoid_compat)
2.311 + {
2.312 + pswit[PARANOID_SWITCH]=!pswit[PARANOID_SWITCH];
2.313 + pswit[TYPO_SWITCH]=!pswit[TYPO_SWITCH];
2.314 + }
2.315 /*
2.316 * Web uploads - for the moment, this is really just a placeholder
2.317 * until we decide what processing we really want to do on web uploads
2.318 @@ -246,6 +475,14 @@
2.319 pswit[USERTYPO_SWITCH]=FALSE;
2.320 pswit[DP_SWITCH]=FALSE;
2.321 }
2.322 + if (pswit[DUMP_CONFIG_SWITCH])
2.323 + {
2.324 + dump_config();
2.325 + exit(0);
2.326 + }
2.327 + if (pswit[OVERVIEW_SWITCH])
2.328 + /* just print summary; don't echo */
2.329 + pswit[ECHO_SWITCH]=FALSE;
2.330 if (*argc<2)
2.331 {
2.332 proghelp(context);
2.333 @@ -388,6 +625,15 @@
2.334 saved_cp=GetConsoleOutputCP();
2.335 #endif
2.336 running_from=g_path_get_dirname(argv[0]);
2.337 + /* Paranoid checking is turned OFF, not on, by its switch */
2.338 + pswit[PARANOID_SWITCH]=TRUE;
2.339 + /* if running in paranoid mode, typo checks default to enabled */
2.340 + pswit[TYPO_SWITCH]=TRUE;
2.341 + /* Line-end checking is turned OFF, not on, by its switch */
2.342 + pswit[LINE_END_SWITCH]=TRUE;
2.343 + /* Echoing is turned OFF, not on, by its switch */
2.344 + pswit[ECHO_SWITCH]=TRUE;
2.345 + parse_config_file();
2.346 parse_options(&argc,&argv);
2.347 if (pswit[USERTYPO_SWITCH])
2.348 read_user_scannos();
2.349 @@ -428,6 +674,8 @@
2.350 g_free(running_from);
2.351 if (usertypo)
2.352 g_tree_unref(usertypo);
2.353 + if (config)
2.354 + g_key_file_free(config);
2.355 return 0;
2.356 }
2.357
3.1 --- a/bookloupe/bookloupe.h Sat Oct 26 18:47:33 2013 +0100
3.2 +++ b/bookloupe/bookloupe.h Fri Oct 25 11:15:18 2013 +0100
3.3 @@ -55,6 +55,7 @@
3.4 MARKUP_SWITCH,
3.5 USERTYPO_SWITCH,
3.6 DP_SWITCH,
3.7 + DUMP_CONFIG_SWITCH,
3.8 SWITNO
3.9 };
3.10
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/sample.ini Fri Oct 25 11:15:18 2013 +0100
4.3 @@ -0,0 +1,31 @@
4.4 +# Default configuration for bookloupe
4.5 +
4.6 +[options]
4.7 +# Ignore DP-specific markup
4.8 +dp=false
4.9 +# Echo queried line
4.10 +echo=true
4.11 +# Check single quotes
4.12 +squote=false
4.13 +# Check common typos
4.14 +typo=true
4.15 +# Require closure of quotes on every paragraph
4.16 +qpara=false
4.17 +# Enable paranoid querying of everything
4.18 +paranoid=true
4.19 +# Enable line end checking
4.20 +line-end=true
4.21 +# Overview: just show counts
4.22 +overview=false
4.23 +# Output errors to stdout instead of stderr
4.24 +stdout=false
4.25 +# Echo header fields
4.26 +header=false
4.27 +# Ignore markup in < >
4.28 +markup=false
4.29 +# Use file of user-defined typos
4.30 +usertypo=false
4.31 +# Defaults for use on www upload
4.32 +web=false
4.33 +# Verbose - list everything
4.34 +verbose=false
5.1 --- a/test/bookloupe/Makefile.am Sat Oct 26 18:47:33 2013 +0100
5.2 +++ b/test/bookloupe/Makefile.am Fri Oct 25 11:15:18 2013 +0100
5.3 @@ -1,6 +1,8 @@
5.4 TESTS_ENVIRONMENT=BOOKLOUPE=../../bookloupe/bookloupe ../harness/loupe-test
5.5 TESTS=non-ascii.tst long-line.tst curved-single-quotes.tst curved-quotes.tst \
5.6 runfox-quotes.tst curved-genitives.tst multi-line-illustration.tst \
5.7 - emdash.tst footnote-marker.tst unix-lineends.tst os9-lineends.tst
5.8 + emdash.tst config-internal.tst config-default.tst config-user.tst \
5.9 + config-override.tst footnote-marker.tst unix-lineends.tst \
5.10 + os9-lineends.tst
5.11
5.12 dist_pkgdata_DATA=$(TESTS)
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/test/bookloupe/config-default.tst Fri Oct 25 11:15:18 2013 +0100
6.3 @@ -0,0 +1,62 @@
6.4 +**************** OPTIONS ****************
6.5 +--dump-config
6.6 +**************** INPUT(bookloupe.ini) ****************
6.7 +# Default configuration for bookloupe
6.8 +
6.9 +[options]
6.10 +# Ignore DP-specific markup
6.11 +dp=false
6.12 +# Echo queried line
6.13 +echo=true
6.14 +# Check single quotes
6.15 +squote=false
6.16 +# Check common typos
6.17 +typo=true
6.18 +# Require closure of quotes on every paragraph
6.19 +qpara=false
6.20 +# Enable paranoid querying of everything
6.21 +paranoid=true
6.22 +# Enable line end checking
6.23 +line-end=true
6.24 +# Overview: just show counts
6.25 +overview=false
6.26 +# Output errors to stdout instead of stderr
6.27 +stdout=false
6.28 +# Echo header fields
6.29 +header=false
6.30 +# Ignore markup in < >
6.31 +markup=false
6.32 +# Use file of user-defined typos
6.33 +usertypo=false
6.34 +# Verbose - list everything
6.35 +verbose=false
6.36 +**************** EXPECTED(stdout) ****************
6.37 +# Default configuration for bookloupe
6.38 +
6.39 +[options]
6.40 +# Ignore DP-specific markup
6.41 +dp=false
6.42 +# Echo queried line
6.43 +echo=true
6.44 +# Check single quotes
6.45 +squote=false
6.46 +# Check common typos
6.47 +typo=true
6.48 +# Require closure of quotes on every paragraph
6.49 +qpara=false
6.50 +# Enable paranoid querying of everything
6.51 +paranoid=true
6.52 +# Enable line end checking
6.53 +line-end=true
6.54 +# Overview: just show counts
6.55 +overview=false
6.56 +# Output errors to stdout instead of stderr
6.57 +stdout=false
6.58 +# Echo header fields
6.59 +header=false
6.60 +# Ignore markup in < >
6.61 +markup=false
6.62 +# Use file of user-defined typos
6.63 +usertypo=false
6.64 +# Verbose - list everything
6.65 +verbose=false
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/test/bookloupe/config-internal.tst Fri Oct 25 11:15:18 2013 +0100
7.3 @@ -0,0 +1,32 @@
7.4 +**************** OPTIONS ****************
7.5 +--dump-config
7.6 +**************** EXPECTED(stdout) ****************
7.7 +# Default configuration for bookloupe
7.8 +
7.9 +[options]
7.10 +# Ignore DP-specific markup
7.11 +dp=false
7.12 +# Echo queried line
7.13 +echo=true
7.14 +# Check single quotes
7.15 +squote=false
7.16 +# Check common typos
7.17 +typo=true
7.18 +# Require closure of quotes on every paragraph
7.19 +qpara=false
7.20 +# Enable paranoid querying of everything
7.21 +paranoid=true
7.22 +# Enable line end checking
7.23 +line-end=true
7.24 +# Overview: just show counts
7.25 +overview=false
7.26 +# Output errors to stdout instead of stderr
7.27 +stdout=false
7.28 +# Echo header fields
7.29 +header=false
7.30 +# Ignore markup in < >
7.31 +markup=false
7.32 +# Use file of user-defined typos
7.33 +usertypo=false
7.34 +# Verbose - list everything
7.35 +verbose=false
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/test/bookloupe/config-override.tst Fri Oct 25 11:15:18 2013 +0100
8.3 @@ -0,0 +1,63 @@
8.4 +**************** OPTIONS ****************
8.5 +--usertypo
8.6 +--dump-config
8.7 +**************** INPUT(bookloupe.ini) ****************
8.8 +# Relaxed configuration for bookloupe
8.9 +
8.10 +[options]
8.11 +# Ignore DP-specific markup
8.12 +dp=false
8.13 +# Echo queried line
8.14 +echo=true
8.15 +# Check single quotes
8.16 +squote=false
8.17 +# Check common typos
8.18 +typo=true
8.19 +# Require closure of quotes on every paragraph
8.20 +qpara=false
8.21 +# Enable paranoid querying of everything
8.22 +paranoid=false
8.23 +# Enable line end checking
8.24 +line-end=true
8.25 +# Overview: just show counts
8.26 +overview=false
8.27 +# Output errors to stdout instead of stderr
8.28 +stdout=false
8.29 +# Echo header fields
8.30 +header=false
8.31 +# Ignore markup in < >
8.32 +markup=false
8.33 +# Use file of user-defined typos
8.34 +usertypo=false
8.35 +# Verbose - list everything
8.36 +verbose=false
8.37 +**************** EXPECTED(stdout) ****************
8.38 +# Relaxed configuration for bookloupe
8.39 +
8.40 +[options]
8.41 +# Ignore DP-specific markup
8.42 +dp=false
8.43 +# Echo queried line
8.44 +echo=true
8.45 +# Check single quotes
8.46 +squote=false
8.47 +# Check common typos
8.48 +typo=true
8.49 +# Require closure of quotes on every paragraph
8.50 +qpara=false
8.51 +# Enable paranoid querying of everything
8.52 +paranoid=false
8.53 +# Enable line end checking
8.54 +line-end=true
8.55 +# Overview: just show counts
8.56 +overview=false
8.57 +# Output errors to stdout instead of stderr
8.58 +stdout=false
8.59 +# Echo header fields
8.60 +header=false
8.61 +# Ignore markup in < >
8.62 +markup=false
8.63 +# Use file of user-defined typos
8.64 +usertypo=true
8.65 +# Verbose - list everything
8.66 +verbose=false
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/test/bookloupe/config-user.tst Fri Oct 25 11:15:18 2013 +0100
9.3 @@ -0,0 +1,72 @@
9.4 +**************** OPTIONS ****************
9.5 +--dump-config
9.6 +**************** INPUT(bookloupe.ini) ****************
9.7 +# Mary Contrary's configuration for bookloupe
9.8 +
9.9 +# Bookloupe will ignore this group, but it's nice to have.
9.10 +[other]
9.11 +# Look at me!
9.12 +name="Mary Contrary"
9.13 +
9.14 +[options]
9.15 +# Ignore DP-specific markup - sounds useful
9.16 +dp=true
9.17 +# Echo queried line - what's the point of that?
9.18 +echo=false
9.19 +# Check single quotes - yup
9.20 +squote=true
9.21 +# Check common typos - waste of time
9.22 +typo=false
9.23 +# Require closure of quotes on every paragraph - okay
9.24 +qpara=true
9.25 +# Enable paranoid querying of everything - Huh?
9.26 +paranoid=false
9.27 +# Enable line end checking - pointless
9.28 +line-end=false
9.29 +# Overview: just show counts - Brief is good
9.30 +overview=true
9.31 +# Output errors to stdout instead of stderr - keeps things together
9.32 +stdout=true
9.33 +# Echo header fields - I'd rather see it
9.34 +header=true
9.35 +# Ignore markup in < > - Need this
9.36 +markup=true
9.37 +# Use file of user-defined typos - And this
9.38 +usertypo=true
9.39 +# Verbose - list everything - Contrary by name...
9.40 +verbose=true
9.41 +**************** EXPECTED(stdout) ****************
9.42 +# Mary Contrary's configuration for bookloupe
9.43 +
9.44 +# Bookloupe will ignore this group, but it's nice to have.
9.45 +[other]
9.46 +# Look at me!
9.47 +name="Mary Contrary"
9.48 +
9.49 +[options]
9.50 +# Ignore DP-specific markup - sounds useful
9.51 +dp=true
9.52 +# Echo queried line - what's the point of that?
9.53 +echo=false
9.54 +# Check single quotes - yup
9.55 +squote=true
9.56 +# Check common typos - waste of time
9.57 +typo=false
9.58 +# Require closure of quotes on every paragraph - okay
9.59 +qpara=true
9.60 +# Enable paranoid querying of everything - Huh?
9.61 +paranoid=false
9.62 +# Enable line end checking - pointless
9.63 +line-end=false
9.64 +# Overview: just show counts - Brief is good
9.65 +overview=true
9.66 +# Output errors to stdout instead of stderr - keeps things together
9.67 +stdout=true
9.68 +# Echo header fields - I'd rather see it
9.69 +header=true
9.70 +# Ignore markup in < > - Need this
9.71 +markup=true
9.72 +# Use file of user-defined typos - And this
9.73 +usertypo=true
9.74 +# Verbose - list everything - Contrary by name...
9.75 +verbose=true
10.1 --- a/test/compatibility/Makefile.am Sat Oct 26 18:47:33 2013 +0100
10.2 +++ b/test/compatibility/Makefile.am Fri Oct 25 11:15:18 2013 +0100
10.3 @@ -6,6 +6,7 @@
10.4 user-defined-typo.tst brackets.tst single-quotes.tst grave-quotes.tst \
10.5 dashes.tst control-characters.tst unusual-characters.tst \
10.6 windows-1252.tst periods.tst long-line.tst unmarked-paragraph.tst \
10.7 + paranoid.tst paranoid-typos.tst no-paranoid.tst no-paranoid-typos.tst \
10.8 hebe-jeebies.tst mail-from.tst scannos.tst before-comma.tst \
10.9 before-period.tst double-punctuation.tst genitives.tst embedded-cr.tst \
10.10 continuing-quotes.tst
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/test/compatibility/no-paranoid-typos.tst Fri Oct 25 11:15:18 2013 +0100
11.3 @@ -0,0 +1,12 @@
11.4 +**************** OPTIONS ****************
11.5 +-x
11.6 +-t
11.7 +**************** INPUT ****************
11.8 +In paranoid mode we check for a standalone digits. 1 think this is a useful
11.9 +feature. When checking for typos every, strangly placed comma is reported.
11.10 +
11.11 +If paranoid mode is switched off, we can still check for typos.
11.12 +**************** EXPECTED ****************
11.13 +
11.14 +feature. When checking for typos every, strangly placed comma is reported.
11.15 + Line 2 column 39 - Query punctuation after every?
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/test/compatibility/no-paranoid.tst Fri Oct 25 11:15:18 2013 +0100
12.3 @@ -0,0 +1,8 @@
12.4 +**************** OPTIONS ****************
12.5 +-x
12.6 +**************** INPUT ****************
12.7 +In paranoid mode we check for a standalone digits. 1 think this is a useful
12.8 +feature. When checking for typos every, strangly placed comma is reported.
12.9 +
12.10 +If paranoid mode is switched off, checking for typos defaults to off too.
12.11 +**************** EXPECTED ****************
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/test/compatibility/paranoid-typos.tst Fri Oct 25 11:15:18 2013 +0100
13.3 @@ -0,0 +1,12 @@
13.4 +**************** OPTIONS ****************
13.5 +-t
13.6 +**************** INPUT ****************
13.7 +In paranoid mode we check for a standalone digits. 1 think this is a useful
13.8 +feature. When checking for typos every, strangly placed comma is reported.
13.9 +
13.10 +In paranoid mode (the default), typo checking is switched off with its
13.11 +short option.
13.12 +**************** EXPECTED ****************
13.13 +
13.14 +In paranoid mode we check for a standalone digits. 1 think this is a useful
13.15 + Line 1 column 51 - Query standalone 1
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/test/compatibility/paranoid.tst Fri Oct 25 11:15:18 2013 +0100
14.3 @@ -0,0 +1,12 @@
14.4 +**************** INPUT ****************
14.5 +In paranoid mode we check for a standalone digits. 1 think this is a useful
14.6 +feature. When checking for typos every, strangly placed comma is reported.
14.7 +
14.8 +By default, both paranoid mode and checking for typos should be on.
14.9 +**************** EXPECTED ****************
14.10 +
14.11 +In paranoid mode we check for a standalone digits. 1 think this is a useful
14.12 + Line 1 column 51 - Query standalone 1
14.13 +
14.14 +feature. When checking for typos every, strangly placed comma is reported.
14.15 + Line 2 column 39 - Query punctuation after every?
15.1 --- a/test/harness/Makefile.am Sat Oct 26 18:47:33 2013 +0100
15.2 +++ b/test/harness/Makefile.am Fri Oct 25 11:15:18 2013 +0100
15.3 @@ -5,5 +5,6 @@
15.4
15.5 loupe_test_SOURCES=loupe-test.c testcase.c testcase.h testcaseio.c \
15.6 testcaseio.h testcaseparser.c testcaseparser.h testcaseinput.c \
15.7 - testcaseinput.h warningsparser.c warningsparser.h
15.8 + testcaseinput.h testcaseoutput.c testcaseoutput.h warningsparser.c \
15.9 + warningsparser.h
15.10 loupe_test_LDADD=../../bl/libbl.la
16.1 --- a/test/harness/loupe-test.c Sat Oct 26 18:47:33 2013 +0100
16.2 +++ b/test/harness/loupe-test.c Fri Oct 25 11:15:18 2013 +0100
16.3 @@ -48,6 +48,7 @@
16.4 exit(1);
16.5 }
16.6 bl_set_print_handlers();
16.7 + g_setenv("BOOKLOUPE_CONFIG_PATH",".",TRUE);
16.8 for(i=1;i<argc;i++)
16.9 pass&=run_test(argv[i]);
16.10 return pass?0:1;
17.1 --- a/test/harness/testcase.c Sat Oct 26 18:47:33 2013 +0100
17.2 +++ b/test/harness/testcase.c Fri Oct 25 11:15:18 2013 +0100
17.3 @@ -7,6 +7,7 @@
17.4 #include <bl/bl.h>
17.5 #include "testcase.h"
17.6 #include "testcaseinput.h"
17.7 +#include "testcaseoutput.h"
17.8
17.9 GQuark testcase_error_quark(void)
17.10 {
17.11 @@ -171,6 +172,64 @@
17.12 return g_string_free(filename,FALSE);
17.13 }
17.14
17.15 +/*
17.16 + * Verify that all the output files specified by a testcase are present
17.17 + * with the expected contents.
17.18 + */
17.19 +gboolean testcase_verify_output_files(Testcase *testcase)
17.20 +{
17.21 + GSList *link;
17.22 + GError *tmp_err=NULL;
17.23 + gboolean retval=TRUE;
17.24 + ssize_t offset;
17.25 + gchar *contents;
17.26 + TestcaseOutput *output;
17.27 + for(link=testcase->outputs;link;link=link->next)
17.28 + {
17.29 + output=link->data;
17.30 + if (!testcase_output_read(testcase,output,&contents,NULL,&tmp_err))
17.31 + {
17.32 + g_print("%s: FAIL\n",testcase->basename);
17.33 + g_print("%s\n",tmp_err->message);
17.34 + g_clear_error(&tmp_err);
17.35 + retval=FALSE;
17.36 + break;
17.37 + }
17.38 + else
17.39 + {
17.40 + if (strcmp(contents,output->contents))
17.41 + {
17.42 + g_print("%s: FAIL\n",testcase->basename);
17.43 + offset=common_prefix_length(contents,output->contents);
17.44 + if (!offset && !contents[offset])
17.45 + g_print("%s: Unexpected empty output from bookloupe.\n",
17.46 + output->name);
17.47 + else
17.48 + {
17.49 + g_print("%s: Unexpected output from bookloupe:\n",
17.50 + output->name);
17.51 + print_unexpected(contents,offset);
17.52 + }
17.53 + retval=FALSE;
17.54 + }
17.55 + g_free(contents);
17.56 + break;
17.57 + }
17.58 + }
17.59 + for(link=testcase->outputs;link;link=link->next)
17.60 + if (!testcase_output_remove(testcase,link->data,&tmp_err))
17.61 + {
17.62 + if (retval)
17.63 + {
17.64 + g_print("%s: FAIL\n",testcase->basename);
17.65 + g_print("%s\n",tmp_err->message);
17.66 + retval=TRUE;
17.67 + }
17.68 + g_clear_error(&tmp_err);
17.69 + }
17.70 + return retval;
17.71 +}
17.72 +
17.73 gboolean testcase_spawn_bookloupe(Testcase *testcase,char **standard_output,
17.74 GError **error)
17.75 {
17.76 @@ -496,7 +555,7 @@
17.77 gboolean r;
17.78 size_t pos,offset;
17.79 GString *header;
17.80 - char *output,*filename,*s,*summary,*xfail=NULL;
17.81 + char *filename,*s,*summary,*xfail=NULL;
17.82 GError *error=NULL;
17.83 if (!testcase_create_input_files(testcase,&error))
17.84 {
17.85 @@ -505,7 +564,7 @@
17.86 g_error_free(error);
17.87 return FALSE;
17.88 }
17.89 - r=testcase_spawn_bookloupe(testcase,&output,&error);
17.90 + r=testcase_spawn_bookloupe(testcase,&testcase->test_output,&error);
17.91 if (!r)
17.92 {
17.93 g_print("%s: FAIL\n",testcase->basename);
17.94 @@ -522,41 +581,47 @@
17.95 g_error_free(error);
17.96 return FALSE;
17.97 }
17.98 - header=g_string_new("\n\nFile: ");
17.99 - g_string_append(header,filename);
17.100 - g_string_append(header,"\n");
17.101 - if (!g_str_has_prefix(output,header->str))
17.102 + if (testcase->expected || testcase->warnings)
17.103 {
17.104 - g_print("%s: FAIL\n",testcase->basename);
17.105 - g_print("Unexpected header from bookloupe:\n");
17.106 - offset=common_prefix_length(output,header->str);
17.107 - print_unexpected(output,offset);
17.108 - r=FALSE;
17.109 - }
17.110 - pos=header->len;
17.111 - if (r)
17.112 - {
17.113 - /* Find the end of the summary */
17.114 - s=strstr(output+pos,"\n\n");
17.115 - if (s)
17.116 - {
17.117 - summary=g_strndup(output+pos,s-(output+pos));
17.118 - r=testcase_check_summary(testcase,summary);
17.119 - g_free(summary);
17.120 - pos=s-output+2;
17.121 - }
17.122 - else
17.123 + header=g_string_new("\n\nFile: ");
17.124 + g_string_append(header,filename);
17.125 + g_string_append(header,"\n");
17.126 + if (!g_str_has_prefix(testcase->test_output,header->str))
17.127 {
17.128 g_print("%s: FAIL\n",testcase->basename);
17.129 - g_print("Unterminated summary from bookloupe:\n%s\n",output+pos);
17.130 + g_print("Unexpected header from bookloupe:\n");
17.131 + offset=common_prefix_length(testcase->test_output,header->str);
17.132 + print_unexpected(testcase->test_output,offset);
17.133 r=FALSE;
17.134 }
17.135 + summary=testcase->test_output+header->len;
17.136 + pos=header->len;
17.137 + if (r)
17.138 + {
17.139 + /* Find the end of the summary */
17.140 + s=strstr(summary,"\n\n");
17.141 + if (s)
17.142 + {
17.143 + summary=g_strndup(summary,s-summary);
17.144 + r=testcase_check_summary(testcase,summary);
17.145 + g_free(summary);
17.146 + pos=s-testcase->test_output+2;
17.147 + }
17.148 + else
17.149 + {
17.150 + g_print("%s: FAIL\n",testcase->basename);
17.151 + g_print("Unterminated summary from bookloupe:\n%s\n",summary);
17.152 + r=FALSE;
17.153 + }
17.154 + }
17.155 + g_string_free(header,TRUE);
17.156 + if (r)
17.157 + r=testcase_check_warnings(testcase,testcase->test_output+pos,
17.158 + &xfail);
17.159 }
17.160 - g_string_free(header,TRUE);
17.161 - if (r)
17.162 - r=testcase_check_warnings(testcase,output+pos,&xfail);
17.163 + if (!testcase_verify_output_files(testcase))
17.164 + r=FALSE;
17.165 g_free(filename);
17.166 - g_free(output);
17.167 if (r)
17.168 {
17.169 if (xfail)
17.170 @@ -617,5 +682,6 @@
17.171 g_slist_free(testcase->warnings);
17.172 g_free(testcase->encoding);
17.173 g_strfreev(testcase->options);
17.174 + g_free(testcase->test_output);
17.175 g_free(testcase);
17.176 }
18.1 --- a/test/harness/testcase.h Sat Oct 26 18:47:33 2013 +0100
18.2 +++ b/test/harness/testcase.h Fri Oct 25 11:15:18 2013 +0100
18.3 @@ -41,11 +41,13 @@
18.4 char *basename;
18.5 char *tmpdir;
18.6 GSList *inputs;
18.7 + GSList *outputs;
18.8 char *expected;
18.9 TestcaseSummary summary;
18.10 GSList *warnings;
18.11 char *encoding; /* The character encoding to talk to BOOKLOUPE in */
18.12 char **options;
18.13 + char *test_output;
18.14 enum {
18.15 TESTCASE_XFAIL=1<<0,
18.16 TESTCASE_TMP_DIR=1<<1,
19.1 --- a/test/harness/testcaseio.c Sat Oct 26 18:47:33 2013 +0100
19.2 +++ b/test/harness/testcaseio.c Fri Oct 25 11:15:18 2013 +0100
19.3 @@ -5,6 +5,7 @@
19.4 #include <bl/bl.h>
19.5 #include "testcaseparser.h"
19.6 #include "testcaseinput.h"
19.7 +#include "testcaseoutput.h"
19.8 #include "testcaseio.h"
19.9 #include "warningsparser.h"
19.10
19.11 @@ -70,6 +71,25 @@
19.12 else if (!testcase->expected && !testcase->warnings &&
19.13 !strcmp(tag,"EXPECTED"))
19.14 testcase->expected=g_strdup(text);
19.15 + else if (g_str_has_prefix(tag,"EXPECTED(") && tag[strlen(tag)-1]==')')
19.16 + {
19.17 + arg=g_strndup(tag+9,strlen(tag)-10);
19.18 + s=g_path_get_dirname(arg);
19.19 + if (strcmp(s,"."))
19.20 + {
19.21 + g_printerr("%s: Expected files may not have a "
19.22 + "directory component\n",arg);
19.23 + g_free(s);
19.24 + g_free(arg);
19.25 + testcase_free(testcase);
19.26 + testcase_parser_free(parser);
19.27 + return NULL;
19.28 + }
19.29 + g_free(s);
19.30 + testcase->outputs=g_slist_prepend(testcase->outputs,
19.31 + testcase_output_new(arg,text));
19.32 + g_free(arg);
19.33 + }
19.34 else if (!testcase->expected && !testcase->warnings &&
19.35 !strcmp(tag,"WARNINGS"))
19.36 {
19.37 @@ -108,11 +128,14 @@
19.38 }
19.39 g_free(s);
19.40 }
19.41 - else if (!testcase->encoding && !strcmp(tag,"OPTIONS"))
19.42 + else if (!testcase->options && !strcmp(tag,"OPTIONS"))
19.43 {
19.44 testcase->options=g_strsplit(text,"\n",0);
19.45 - g_free(testcase->options[g_strv_length(testcase->options)-1]);
19.46 - testcase->options[g_strv_length(testcase->options)-1]=NULL;
19.47 + if (testcase->options && g_strv_length(testcase->options)>0)
19.48 + {
19.49 + g_free(testcase->options[g_strv_length(testcase->options)-1]);
19.50 + testcase->options[g_strv_length(testcase->options)-1]=NULL;
19.51 + }
19.52 }
19.53 else
19.54 {
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/test/harness/testcaseoutput.c Fri Oct 25 11:15:18 2013 +0100
20.3 @@ -0,0 +1,140 @@
20.4 +#include <stdlib.h>
20.5 +#include <string.h>
20.6 +#include <errno.h>
20.7 +#include <glib.h>
20.8 +#include <bl/bl.h>
20.9 +#include "testcase.h"
20.10 +#include "testcaseoutput.h"
20.11 +
20.12 +/*
20.13 + * Replace \r\n with \n, \n with U+240A (visible symbol for LF)
20.14 + * and \r with U+240D (visible symbol for CR).
20.15 + */
20.16 +static char *dos2unix(const char *text)
20.17 +{
20.18 + gunichar c;
20.19 + gboolean cr=FALSE;
20.20 + const gunichar visible_lf=0x240A;
20.21 + const gunichar visible_cr=0x240D;
20.22 + GString *string;
20.23 + string=g_string_new(NULL);
20.24 + while(*text)
20.25 + {
20.26 + c=g_utf8_get_char(text);
20.27 + text=g_utf8_next_char(text);
20.28 + if (cr)
20.29 + {
20.30 + cr=FALSE;
20.31 + if (c=='\n')
20.32 + {
20.33 + g_string_append_c(string,'\n');
20.34 + continue;
20.35 + }
20.36 + else
20.37 + g_string_append_unichar(string,visible_cr);
20.38 + }
20.39 + if (c=='\r')
20.40 + cr=TRUE;
20.41 + else if (c=='\n')
20.42 + g_string_append_unichar(string,visible_lf);
20.43 + else
20.44 + g_string_append_unichar(string,c);
20.45 + }
20.46 + if (cr)
20.47 + g_string_append_unichar(string,visible_cr);
20.48 + return g_string_free(string,FALSE);
20.49 +}
20.50 +
20.51 +/*
20.52 + * Read an output file needed for a testcase (as specified in <output>).
20.53 + * The file is read in the encoding specified for communicating with
20.54 + * bookloupe.
20.55 + */
20.56 +gboolean testcase_output_read(Testcase *testcase,TestcaseOutput *output,
20.57 + gchar **contents,gsize *length,GError **error)
20.58 +{
20.59 + char *filename,*s,*t;
20.60 + gboolean retval;
20.61 + GError *tmp_err=NULL;
20.62 + if (!strcmp(output->name,"stdout"))
20.63 + {
20.64 + *contents=g_strdup(testcase->test_output);
20.65 + if (length)
20.66 + *length=strlen(testcase->test_output);
20.67 + }
20.68 + else
20.69 + {
20.70 + if (testcase->tmpdir)
20.71 + filename=g_build_filename(testcase->tmpdir,output->name,NULL);
20.72 + else
20.73 + filename=g_strdup(output->name);
20.74 + if (!g_file_get_contents(filename,&s,NULL,error))
20.75 + {
20.76 + g_free(filename);
20.77 + return FALSE;
20.78 + }
20.79 + g_free(filename);
20.80 + if (testcase->encoding)
20.81 + {
20.82 + t=dos2unix(s);
20.83 + g_free(s);
20.84 + s=g_convert(t,-1,"UTF-8",testcase->encoding,NULL,length,&tmp_err);
20.85 + g_free(t);
20.86 + if (!s)
20.87 + {
20.88 + g_propagate_prefixed_error(error,tmp_err,
20.89 + "Conversion from %s failed: ",testcase->encoding);
20.90 + return FALSE;
20.91 + }
20.92 + *contents=s;
20.93 + }
20.94 + else
20.95 + {
20.96 + *contents=dos2unix(s);
20.97 + if (length)
20.98 + *length=strlen(*contents);
20.99 + }
20.100 + }
20.101 + return TRUE;
20.102 +}
20.103 +
20.104 +/*
20.105 + * Remove an output file created by program under test.
20.106 + */
20.107 +gboolean testcase_output_remove(Testcase *testcase,TestcaseOutput *output,
20.108 + GError **error)
20.109 +{
20.110 + char *filename;
20.111 + if (!strcmp(output->name,"stdout"))
20.112 + return TRUE;
20.113 + if (testcase->tmpdir)
20.114 + filename=g_build_filename(testcase->tmpdir,output->name,NULL);
20.115 + else
20.116 + filename=g_strdup(output->name);
20.117 + if (g_unlink(filename)<0)
20.118 + {
20.119 + g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
20.120 + "%s: %s",filename,g_strerror(errno));
20.121 + return FALSE;
20.122 + }
20.123 + g_free(filename);
20.124 + return TRUE;
20.125 +}
20.126 +
20.127 +/* Create a new description of an output file expected by a testcase */
20.128 +TestcaseOutput *testcase_output_new(const char *name,const char *contents)
20.129 +{
20.130 + TestcaseOutput *output;
20.131 + output=g_new0(TestcaseOutput,1);
20.132 + output->name=g_strdup(name);
20.133 + output->contents=g_strdup(contents);
20.134 + return output;
20.135 +}
20.136 +
20.137 +/* Free the description of a testcase output file */
20.138 +void testcase_output_free(TestcaseOutput *output)
20.139 +{
20.140 + g_free(output->name);
20.141 + g_free(output->contents);
20.142 + g_free(output);
20.143 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/test/harness/testcaseoutput.h Fri Oct 25 11:15:18 2013 +0100
21.3 @@ -0,0 +1,19 @@
21.4 +#ifndef TESTCASE_OUTPUT_H
21.5 +#define TESTCASE_OUTPUT_H
21.6 +
21.7 +#include <glib.h>
21.8 +#include "testcase.h"
21.9 +
21.10 +typedef struct {
21.11 + char *name;
21.12 + char *contents;
21.13 +} TestcaseOutput;
21.14 +
21.15 +gboolean testcase_output_read(Testcase *testcase,TestcaseOutput *output,
21.16 + gchar **contents,gsize *length,GError **error);
21.17 +gboolean testcase_output_remove(Testcase *testcase,TestcaseOutput *output,
21.18 + GError **error);
21.19 +TestcaseOutput *testcase_output_new(const char *name,const char *contents);
21.20 +void testcase_output_free(TestcaseOutput *output);
21.21 +
21.22 +#endif /* TESTCASE_OUTPUT_H */