/*
* libzvbi test
*
* Copyright (C) 2000, 2001 Michael H. Schimek
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: explist.c,v 1.10 2006/02/10 06:25:38 mschimek Exp $ */
#undef NDEBUG
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#endif
#include <locale.h>
#include "src/libzvbi.h"
#ifndef _
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(String) dgettext (PACKAGE, String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
/* Stubs that do something close enough. */
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define N_(String) (String)
#endif
#endif
vbi_bool check = FALSE;
#define TYPE_STR(type) case type : type_str = #type ; break
#define INT_TYPE(oi) ((oi)->type == VBI_OPTION_BOOL \
|| (oi)->type == VBI_OPTION_INT \
|| (oi)->type == VBI_OPTION_MENU)
#define REAL_TYPE(oi) ((oi)->type == VBI_OPTION_REAL)
#define MENU_TYPE(oi) ((oi)->menu.str != NULL)
#define ASSERT_ERRSTR(expr) \
do { \
if (!(expr)) { \
printf("Assertion '" #expr "' failed; errstr=\"%s\"\n", \
vbi_export_errstr(ex)); \
exit(EXIT_FAILURE); \
} \
} while (0)
#define BOUNDS_CHECK(type) \
do { \
if (oi->menu.type) { \
assert(oi->def.num >= 0); \
assert(oi->def.num <= oi->max.num); \
assert(oi->min.num == 0); \
assert(oi->max.num > 0); \
assert(oi->step.num == 1); \
} else { \
assert(oi->max.type >= oi->min.type); \
assert(oi->step.type > 0); \
assert(oi->def.type >= oi->min.type \
&& oi->def.type <= oi->max.type); \
} \
} while (0)
#define STRING_CHECK(type) \
do { \
if (oi->menu.type) { \
assert(oi->def.num >= 0); \
assert(oi->def.num <= oi->max.num); \
assert(oi->min.num == 0); \
assert(oi->max.num > 0); \
assert(oi->step.num == 1); \
} else { \
assert(oi->def.str != NULL); \
} \
} while (0)
static void
keyword_check(char *keyword)
{
int i, l;
assert(keyword != NULL);
l = strlen(keyword);
assert(strlen(keyword) > 0);
for (i = 0; i < l; i++) {
if (isalnum(keyword[i]))
continue;
if (strchr("_", keyword[i]))
continue;
fprintf(stderr, "Bad keyword: '%s'\n", keyword);
exit(EXIT_FAILURE);
}
}
static void
print_current(vbi_option_info *oi, vbi_option_value current)
{
if (REAL_TYPE(oi)) {
printf(" current value=%f\n", current.dbl);
if (!oi->menu.dbl)
assert(current.dbl >= oi->min.dbl
&& current.dbl <= oi->max.dbl);
} else {
printf(" current value=%d\n", current.num);
if (!oi->menu.num)
assert(current.num >= oi->min.num
&& current.num <= oi->max.num);
}
}
static void
test_modified(vbi_option_info *oi, vbi_option_value old, vbi_option_value new)
{
if (REAL_TYPE(oi)) {
/* XXX unsafe */
if (old.dbl != new.dbl) {
printf("but modified current value to %f\n", new.dbl);
exit(EXIT_FAILURE);
}
} else {
if (old.num != new.num) {
printf("but modified current value to %d\n", new.num);
exit(EXIT_FAILURE);
}
}
}
static void
test_set_int(vbi_export *ex, vbi_option_info *oi,
vbi_option_value *current, int value)
{
vbi_option_value new_current;
vbi_bool r;
printf(" try to set %d: ", value);
r = vbi_export_option_set(ex, oi->keyword, value);
if (r)
printf("success.");
else
printf("failed, errstr=\"%s\".", vbi_export_errstr(ex));
new_current.num = 0x54321;
if (!vbi_export_option_get(ex, oi->keyword, &new_current)) {
printf("vbi_export_option_get failed, errstr==\"%s\"\n",
vbi_export_errstr(ex));
if (new_current.num != 0x54321)
printf("but modified destination to %d\n",
new_current.num);
exit(EXIT_FAILURE);
}
if (!r)
test_modified(oi, *current, new_current);
print_current(oi, *current = new_current);
}
static void
test_set_real(vbi_export *ex, vbi_option_info *oi,
vbi_option_value *current, double value)
{
vbi_option_value new_current;
vbi_bool r;
printf(" try to set %f: ", value);
r = vbi_export_option_set(ex, oi->keyword, value);
if (r)
printf("success.");
else
printf("failed, errstr=\"%s\".", vbi_export_errstr(ex));
new_current.dbl = 8192.0;
if (!vbi_export_option_get(ex, oi->keyword, &new_current)) {
printf("vbi_export_option_get failed, errstr==\"%s\"\n",
vbi_export_errstr(ex));
/* XXX unsafe */
if (new_current.dbl != 8192.0)
printf("but modified destination to %f\n",
new_current.dbl);
exit(EXIT_FAILURE);
}
if (!r)
test_modified(oi, *current, new_current);
print_current(oi, *current = new_current);
}
static void
test_set_entry(vbi_export *ex, vbi_option_info *oi,
vbi_option_value *current, int entry)
{
vbi_option_value new_current;
int new_entry;
vbi_bool r0, r1;
vbi_bool valid;
valid = (MENU_TYPE(oi)
&& entry >= oi->min.num
&& entry <= oi->max.num);
printf(" try to set menu entry %d: ", entry);
r0 = vbi_export_option_menu_set(ex, oi->keyword, entry);
switch (r0 = r0 * 2 + valid) {
case 0:
printf("failed as expected, errstr=\"%s\".", vbi_export_errstr(ex));
break;
case 1:
printf("failed, errstr=\"%s\".", vbi_export_errstr(ex));
break;
case 2:
printf("unexpected success.");
break;
default:
printf("success.");
}
ASSERT_ERRSTR(vbi_export_option_get(ex, oi->keyword, &new_current));
if (r0 == 0 || r0 == 1)
test_modified(oi, *current, new_current);
valid = MENU_TYPE(oi);
new_entry = 0x33333;
r1 = vbi_export_option_menu_get(ex, oi->keyword, &new_entry);
switch (r1 = r1 * 2 + valid) {
case 1:
printf("\nvbi_export_option_menu_get failed, errstr==\"%s\"\n",
vbi_export_errstr(ex));
break;
case 2:
printf("\nvbi_export_option_menu_get: unexpected success.\n");
break;
default:
break;
}
if ((r1 == 0 || r1 == 1) && new_entry != 0x33333) {
printf("vbi_export_option_menu_get failed, "
"but modified destination to %d\n",
new_current.num);
exit(EXIT_FAILURE);
}
if (r0 == 1 || r0 == 2 || r1 == 1 || r1 == 2)
exit(EXIT_FAILURE);
switch (oi->type) {
case VBI_OPTION_BOOL:
case VBI_OPTION_INT:
if (oi->menu.num)
assert(new_current.num == oi->menu.num[new_entry]);
else
test_modified(oi, *current, new_current);
print_current(oi, *current = new_current);
break;
case VBI_OPTION_REAL:
if (oi->menu.dbl) {
/* XXX unsafe */
assert(new_current.dbl == oi->menu.dbl[new_entry]);
} else {
test_modified(oi, *current, new_current);
}
print_current(oi, *current = new_current);
break;
case VBI_OPTION_MENU:
print_current(oi, *current = new_current);
break;
default:
assert(!"reached");
break;
}
}
static void
dump_option_info(vbi_export *ex, vbi_option_info *oi)
{
vbi_option_value val;
char *type_str;
int i;
switch (oi->type) {
TYPE_STR(VBI_OPTION_BOOL);
TYPE_STR(VBI_OPTION_INT);
TYPE_STR(VBI_OPTION_REAL);
TYPE_STR(VBI_OPTION_STRING);
TYPE_STR(VBI_OPTION_MENU);
default:
printf(" * Option %s has invalid type %d\n", oi->keyword, oi->type);
exit(EXIT_FAILURE);
}
printf(" * type=%s keyword=%s label=\"%s\" tooltip=\"%s\"\n",
type_str, oi->keyword, _(oi->label), _(oi->tooltip));
keyword_check(oi->keyword);
switch (oi->type) {
case VBI_OPTION_BOOL:
case VBI_OPTION_INT:
BOUNDS_CHECK(num);
if (oi->menu.num) {
printf(" %d menu entries, default=%d: ",
oi->max.num - oi->min.num + 1, oi->def.num);
for (i = oi->min.num; i <= oi->max.num; i++)
printf("%d%s", oi->menu.num[i],
(i < oi->max.num) ? ", " : "");
printf("\n");
} else
printf(" default=%d, min=%d, max=%d, step=%d\n",
oi->def.num, oi->min.num, oi->max.num, oi->step.num);
ASSERT_ERRSTR(vbi_export_option_get(ex, oi->keyword, &val));
print_current(oi, val);
if (check) {
if (oi->menu.num) {
test_set_entry(ex, oi, &val, oi->min.num);
test_set_entry(ex, oi, &val, oi->max.num);
test_set_entry(ex, oi, &val, oi->min.num - 1);
test_set_entry(ex, oi, &val, oi->max.num + 1);
test_set_int(ex, oi, &val, oi->menu.num[oi->min.num]);
test_set_int(ex, oi, &val, oi->menu.num[oi->max.num]);
test_set_int(ex, oi, &val, oi->menu.num[oi->min.num] - 1);
test_set_int(ex, oi, &val, oi->menu.num[oi->max.num] + 1);
} else {
test_set_entry(ex, oi, &val, 0);
test_set_int(ex, oi, &val, oi->min.num);
test_set_int(ex, oi, &val, oi->max.num);
test_set_int(ex, oi, &val, oi->min.num - 1);
test_set_int(ex, oi, &val, oi->max.num + 1);
}
}
break;
case VBI_OPTION_REAL:
BOUNDS_CHECK(dbl);
if (oi->menu.dbl) {
printf(" %d menu entries, default=%d: ",
oi->max.num - oi->min.num + 1, oi->def.num);
for (i = oi->min.num; i <= oi->max.num; i++)
printf("%f%s", oi->menu.dbl[i],
(i < oi->max.num) ? ", " : "");
} else
printf(" default=%f, min=%f, max=%f, step=%f\n",
oi->def.dbl, oi->min.dbl, oi->max.dbl, oi->step.dbl);
ASSERT_ERRSTR(vbi_export_option_get(ex, oi->keyword, &val));
print_current(oi, val);
if (check) {
if (oi->menu.num) {
test_set_entry(ex, oi, &val, oi->min.num);
test_set_entry(ex, oi, &val, oi->max.num);
test_set_entry(ex, oi, &val, oi->min.num - 1);
test_set_entry(ex, oi, &val, oi->max.num + 1);
test_set_real(ex, oi, &val, oi->menu.dbl[oi->min.num]);
test_set_real(ex, oi, &val, oi->menu.dbl[oi->max.num]);
test_set_real(ex, oi, &val, oi->menu.dbl[oi->min.num] - 1);
test_set_real(ex, oi, &val, oi->menu.dbl[oi->max.num] + 1);
} else {
test_set_entry(ex, oi, &val, 0);
test_set_real(ex, oi, &val, oi->min.dbl);
test_set_real(ex, oi, &val, oi->max.dbl);
test_set_real(ex, oi, &val, oi->min.dbl - 1);
test_set_real(ex, oi, &val, oi->max.dbl + 1);
}
}
break;
case VBI_OPTION_STRING:
if (oi->menu.str) {
STRING_CHECK(str);
printf(" %d menu entries, default=%d: ",
oi->max.num - oi->min.num + 1, oi->def.num);
for (i = oi->min.num; i <= oi->max.num; i++)
printf("%s%s", oi->menu.str[i],
(i < oi->max.num) ? ", " : "");
} else
printf(" default=\"%s\"\n", oi->def.str);
ASSERT_ERRSTR(vbi_export_option_get(ex, oi->keyword, &val));
printf(" current value=\"%s\"\n", val.str);
assert(val.str);
free(val.str);
if (check) {
printf(" try to set \"foobar\": ");
if (vbi_export_option_set(ex, oi->keyword, "foobar"))
printf("success.");
else
printf("failed, errstr=\"%s\".", vbi_export_errstr(ex));
ASSERT_ERRSTR(vbi_export_option_get(ex, oi->keyword, &val));
printf(" current value=\"%s\"\n", val.str);
assert(val.str);
free(val.str);
}
break;
case VBI_OPTION_MENU:
printf(" %d menu entries, default=%d: ",
oi->max.num - oi->min.num + 1, oi->def.num);
for (i = oi->min.num; i <= oi->max.num; i++) {
assert(oi->menu.str[i] != NULL);
printf("%s%s", _(oi->menu.str[i]),
(i < oi->max.num) ? ", " : "");
}
printf("\n");
ASSERT_ERRSTR(vbi_export_option_get(ex, oi->keyword, &val));
print_current(oi, val);
if (check) {
test_set_entry(ex, oi, &val, oi->min.num);
test_set_entry(ex, oi, &val, oi->max.num);
test_set_entry(ex, oi, &val, oi->min.num - 1);
test_set_entry(ex, oi, &val, oi->max.num + 1);
}
break;
default:
assert(!"reached");
break;
}
}
static void
list_options(vbi_export *ex)
{
vbi_option_info *oi;
int i;
puts(" List of options:");
for (i = 0; (oi = vbi_export_option_info_enum(ex, i)); i++) {
assert(oi->keyword != NULL);
ASSERT_ERRSTR(oi == vbi_export_option_info_keyword(ex, oi->keyword));
dump_option_info(ex, oi);
}
}
static void
list_modules(void)
{
vbi_export_info *xi;
vbi_export *ex;
char *errstr;
int i;
puts("List of export modules:");
for (i = 0; (xi = vbi_export_info_enum(i)); i++) {
assert(xi->keyword != NULL);
assert(xi == vbi_export_info_keyword(xi->keyword));
printf("* keyword=%s label=\"%s\"\n"
" tooltip=\"%s\" mime_type=%s extension=%s\n",
xi->keyword, _(xi->label),
_(xi->tooltip), xi->mime_type, xi->extension);
keyword_check(xi->keyword);
if (!(ex = vbi_export_new(xi->keyword, &errstr))) {
printf("Could not open '%s': %s\n",
xi->keyword, errstr);
exit(EXIT_FAILURE);
}
ASSERT_ERRSTR(xi == vbi_export_info_export(ex));
list_options(ex);
vbi_export_delete(ex);
}
puts("-- end of list --");
}
static const char short_options[] = "c";
#ifdef HAVE_GETOPT_LONG
static const struct option
long_options[] = {
{ "check", no_argument, NULL, 'c' },
{ 0, 0, 0, 0 }
};
#else
#define getopt_long(ac, av, s, l, i) getopt(ac, av, s)
#endif
int
main(int argc, char **argv)
{
int index, c;
setlocale (LC_ALL, "");
textdomain ("foobar"); /* we are not the library */
while ((c = getopt_long(argc, argv, short_options,
long_options, &index)) != -1)
switch (c) {
case 'c':
check = TRUE;
break;
default:
fprintf(stderr, "Unknown option\n");
exit(EXIT_FAILURE);
}
list_modules();
exit(EXIT_SUCCESS);
}
syntax highlighted by Code2HTML, v. 0.9.1