(linenum→info "unix/slp.c:2238")

anthy/9100e/test/main.c

    1: /* ライブラリの関数呼び出しのテスト
    2:  *
    3:  * デフォルトでは、test.txtから1行ずつ読み込んで変換を行う。
    4:  * 変換前の文字列と変換を行った結果をtest.expから探し、
    5:  * 変換結果が合っているかをカウントして最後に出力する。
    6:  *
    7:  * ./anthy --from 1 --to 10 のように実行するとtest.txtの最初の10個の
    8:  *  行の変換テストが行われます。
    9:  *
   10:  * --askオプションを付けて実行すると、結果が合っているかの判断を
   11:  * 設定するモードになるので、表示された結果に対する判断を
   12:  * 標準入力から'y', 'n', 'd', 'q'で入力してください。
   13:  * 'd' dont care, 'q' quit
   14:  * 判断できない場合はその他の文字を入力してください。
   15:  *
   16:  * Copyright (C) 2000-2006 TABATA Yusuke
   17:  * Copyright (C) 2004-2006 YOSHIDA Yuichi
   18:  * Copyright (C) 2001-2002 TAKAI Kosuke
   19:  *
   20:  */
   21: 
   22: #include <stdio.h>
   23: #include <string.h>
   24: #include <stdlib.h>
   25: #include <time.h>
   26: 
   27: #include <anthy/anthy.h>
   28: #include <anthy/convdb.h>
   29: #include <config.h>
   30: 
   31: /* Makefile の $(srcdir) (静的データファイルの基準ディレクトリ) */
   32: #ifndef SRCDIR
   33: # define SRCDIR "."
   34: #endif
   35: /* ビルド時のカレントディレクトリ (ここに .anthy を作る) */
   36: #ifndef TEST_HOME
   37: # define TEST_HOME "."          /* FIXME: 実際は相対パスだと誤動作する */
   38: #endif
   39: 
   40: /* テストデータとなる変換前の文字列 */
   41: #define TESTDATA "test.txt"
   42: const char *testdata = SRCDIR "/" TESTDATA;
   43: 
   44: /* 変換後の文字列が妥当かどうかをチェックするためのデータ */
   45: #define EXPDATA "test.exp"
   46: const char *expdata = SRCDIR "/" EXPDATA;
   47: 
   48: struct input {
   49:   char *str;
   50:   int serial;
   51: };
   52: 
   53: /* テストを行う条件 */
   54: struct condition {
   55:   /* conversion condition */
   56:   int serial;
   57:   int from;
   58:   int to;
   59:   /* operation */
   60:   int ask;
   61:   int quiet;
   62:   int miss_only;
   63:   int use_utf8;
   64: };
   65: 
   66: static int
   67: read_file(FILE *fp, struct input *in)
   68: {
   69:   char buf[256];
   70:   while(fgets(buf, 256, fp)) {
   71:     switch(buf[0]){
   72:     case '#':
   73:     case ':':
   74:     case '-':
   75:       break;
   76:     case '*':
   77:       if (in->str) {
   78:         free(in->str);
   79:         in->str = 0;
   80:       }
   81:       buf[strlen(buf)-1] = 0;
   82:       in->str = strdup(&buf[1]);
   83:       in->serial ++;
   84:       return 0;
   85:       break;
   86:     }
   87:   }
   88:   return -1;
   89: }
   90: 
   91: static int
   92: check_cond(struct condition *cond, struct input *in)
   93: {
   94:   if (in->serial == cond->serial) {
   95:     return 1;
   96:   }
   97:   if (in->serial <= cond->to && in->serial >= cond->from) {
   98:     return 1;
   99:   }
  100:   return 0;
  101: }
  102: 
  103: static void
  104: log_print(int lv, const char *msg)
  105: {
  106:   printf("log:%d:%s\n", lv, msg);
  107: }
  108: 
  109: static anthy_context_t
  110: init_lib(int use_utf8)
  111: {
  112:   anthy_context_t ac;
  113:   /* 既にインストールされているファイルの影響を受けないようにする */
  114:   anthy_conf_override("CONFFILE", "../anthy-conf");
  115:   anthy_conf_override("HOME", TEST_HOME);
  116:   anthy_conf_override("DIC_FILE", "../mkanthydic/anthy.dic");
  117:   anthy_set_logger(log_print, 0);
  118:   if (anthy_init()) {
  119:     printf("failed to init anthy\n");
  120:     exit(0);
  121:   }
  122:   anthy_set_personality("");
  123: 
  124:   ac = anthy_create_context();
  125:   if (use_utf8) {
  126:     anthy_context_set_encoding(ac, ANTHY_UTF8_ENCODING);
  127:   } else {
  128:     anthy_context_set_encoding(ac, ANTHY_EUC_JP_ENCODING);
  129:   }
  130:   return ac;
  131: }
  132: 
  133: static void
  134: print_usage(void)
  135: {
  136:   printf("Anthy "VERSION"\n"
  137:          "./anthy [test-id]\n"
  138:          " For example.\n"
  139:          "  ./anthy 1\n"
  140:          "  ./anthy --to 100\n"
  141:          "  ./anthy --from 10 --to 100\n"
  142:          "  ./anthy --all --print-miss-only --ask\n"
  143:          "  ./anthy --ll 1\n\n");
  144:   exit(0);
  145: }
  146: 
  147: static void
  148: parse_args(struct condition *cond, int argc, char **argv)
  149: {
  150:   int i;
  151:   char *arg;
  152:   for (i = 1; i < argc; i++) {
  153:     arg = argv[i];
  154:     if (!strncmp(arg, "--", 2)) {
  155:       arg = &arg[2];
  156:       if (!strcmp(arg, "help") || !strcmp(arg, "version")) {
  157:         print_usage();
  158:       }
  159:       if (!strcmp(arg, "all")) {
  160:         cond->from = 0;
  161:         cond->to = 100000000;
  162:       } else if (!strcmp(arg, "quiet")) {
  163:         cond->quiet = 1;
  164:       } else if (!strcmp(arg, "ask") ||
  165:                  !strcmp(arg, "query")) {
  166:         cond->ask = 1;
  167:       } else if (!strcmp(arg, "print-miss-only")) {
  168:         cond->miss_only = 1;
  169:       } else if (!strcmp(arg, "utf8")) {
  170:         cond->use_utf8 = 1;
  171:       }
  172: 
  173:       if (i + 1 < argc) {
  174:         if (!strcmp(arg, "from")){
  175:           cond->from = atoi(argv[i+1]);
  176:           i++;
  177:         }else if (!strcmp(arg, "to")){
  178:           cond->to = atoi(argv[i+1]);
  179:           i++;
  180:         }else if (!strcmp(arg, "ll")) {
  181:           anthy_set_logger(NULL, atoi(argv[i+1]));
  182:           i++;
  183:         }
  184:       }
  185:     } else {
  186:       int num = atoi(arg);
  187:       if (num) {
  188:         cond->serial = num;
  189:       } else {
  190:         char *buf = alloca(strlen(SRCDIR)+strlen(arg) + 10);
  191:         sprintf(buf, SRCDIR "/%s.txt", arg);
  192:         testdata = strdup(buf);
  193:       }
  194:     }
  195:   }
  196: }
  197: 
  198: static void
  199: print_run_env(void)
  200: {
  201:   time_t t;
  202:   const char *env;
  203:   env = getenv("ANTHY_ENABLE_DEBUG_PRINT");
  204:   if (!env) {
  205:     env = "";
  206:   }
  207:   printf("ANTHY_ENABLE_DEBUG_PRINT=(%s)\n", env);
  208:   env = getenv("ANTHY_SPLITTER_PRINT");
  209:   if (!env) {
  210:     env = "";
  211:   }
  212:   printf("ANTHY_SPLITTER_PRINT=(%s)\n", env);
  213:   printf("SRCDIR=(%s)\n", SRCDIR);
  214:   t = time(&t);
  215:   printf(PACKAGE "-" VERSION " %s", ctime(&t));
  216: }
  217: 
  218: static void
  219: sum_up(struct res_db *db, struct conv_res *cr)
  220: {
  221:   int is_split;
  222:   struct res_stat *rs;
  223:   cr->used = 1;
  224:   db->total ++;
  225:   if (cr->res_str[0] == '|') {
  226:     rs = &db->split;
  227:     is_split = 1;
  228:   } else {
  229:     rs = &db->res;
  230:     is_split = 0;
  231:   }
  232:   if (cr->check == CHK_OK) {
  233:     rs->ok ++;
  234:   } else if (cr->check == CHK_MISS) {
  235:     rs->miss ++;
  236:   } else if (cr->check == CHK_DONTCARE) {
  237:     rs->dontcare ++;
  238:   } else {
  239:     rs->unknown ++;
  240:   }
  241: }
  242: 
  243: static void
  244: set_string(struct condition *cond, struct res_db *db,
  245:            struct input *in, anthy_context_t ac)
  246: {
  247:   struct conv_res *cr1, *cr2;
  248:   int pr;
  249: 
  250:   anthy_set_string(ac, in->str);
  251: 
  252:   /* result */
  253:   cr1 = find_conv_res(db, ac, in->str, 1);
  254:   sum_up(db, cr1);
  255:   /* split */
  256:   cr2 = find_conv_res(db, ac, in->str, 0);
  257:   sum_up(db, cr2);
  258: 
  259:   /**/
  260:   pr = 0;
  261:   if (cond->miss_only) {
  262:     if (cr1->check == CHK_MISS ||
  263:         cr2->check == CHK_MISS) {
  264:       pr = 1;
  265:     }
  266:   } else if (!cond->quiet) {
  267:     pr = 1;
  268:   }
  269: 
  270:   if (pr) {
  271:     printf("%d:(%s)\n", in->serial, in->str);
  272:     anthy_print_context(ac);
  273:   }
  274:   anthy_reset_context(ac);
  275: }
  276: 
  277: 
  278: static void
  279: dump_res(FILE *fp, struct conv_res *r)
  280: {
  281:   fprintf(fp, "%s %s ", r->src_str, r->res_str);
  282:   if (r->check == CHK_MISS) {
  283:     fprintf(fp, "X");
  284:   } else if (r->check == CHK_OK) {
  285:     fprintf(fp, "OK");
  286:   } else if (r->check == CHK_DONTCARE) {
  287:     fprintf(fp, "*");
  288:   } else {
  289:     fprintf(fp, "?");
  290:   }
  291:   fprintf(fp, "\n");
  292: }
  293: 
  294: static void
  295: save_db(const char *fn, struct res_db *db)
  296: {
  297:   FILE *fp = fopen(fn, "w");
  298:   struct conv_res *cr;
  299:   if (!fp) {
  300:     printf("failed to open (%s) to write\n", fn);
  301:     return ;
  302:   }
  303:   for (cr = db->res_list.next; cr; cr = cr->next) {
  304:     dump_res(fp, cr);
  305:   }
  306: }
  307: 
  308: static void
  309: ask_results(struct res_db *db)
  310: {
  311:   struct conv_res *cr;
  312:   for (cr = db->res_list.next; cr; cr = cr->next) {
  313:     if (cr->check == CHK_UNKNOWN && cr->used == 1) {
  314:       char buf[256];
  315:       printf("%s -> %s (y/n/d/q)\n", cr->src_str, cr->res_str);
  316:       fgets(buf, 256, stdin);
  317:       if (buf[0] == 'y') {
  318:         cr->check = CHK_OK;
  319:       } else if (buf[0] == 'n') {
  320:         cr->check = CHK_MISS;
  321:       } else if (buf[0] == 'd') {
  322:         cr->check = CHK_DONTCARE;
  323:       } else if (buf[0] == 'q') {
  324:         return ;
  325:       }
  326:     }
  327:   }
  328: }
  329: 
  330: static void
  331: show_stat(struct res_db *db)
  332: {
  333:   struct res_stat *rs;
  334:   int i;
  335:   /**/
  336:   printf("%d items\n", db->total);
  337:   for (i = 0; i < 2; i++) {
  338:     if (i == 0) {
  339:       printf("conversion result\n");
  340:       rs = &db->res;
  341:     } else {
  342:       printf("split result\n");
  343:       rs = &db->split;
  344:     }
  345:     printf("ok : %d\n", rs->ok);
  346:     printf("miss : %d\n", rs->miss);
  347:     printf("unknown : %d\n", rs->unknown);
  348:     printf("\n");
  349:   }
  350: }
  351: 
  352: static void
  353: init_condition(struct condition *cond)
  354: {
  355:   cond->serial = 0;
  356:   cond->from = 0;
  357:   cond->to = 0;
  358:   /**/
  359:   cond->quiet = 0;
  360:   cond->ask = 0;
  361:   cond->miss_only = 0;
  362:   cond->use_utf8 = 0;
  363: }
  364: 
  365: int
  366: main(int argc,char **argv)
  367: {
  368:   anthy_context_t ac;
  369:   FILE *fp;
  370:   struct input cur_input;
  371:   struct res_db *db;
  372:   struct condition cond;
  373: 
  374:   cur_input.serial = 0;
  375:   cur_input.str = 0;
  376:   init_condition(&cond);
  377: 
  378:   parse_args(&cond, argc, argv);
  379:   db = create_db();
  380:   read_db(db, expdata);
  381: 
  382:   printf("./test_anthy --help to print usage.\n");
  383: 
  384:   print_run_env();
  385: 
  386:   fp = fopen(testdata, "r");
  387:   if (!fp) {
  388:     printf("failed to open %s.\n", testdata);
  389:     return 0;
  390:   }
  391:   
  392:   ac = init_lib(cond.use_utf8);
  393: 
  394:   /* ファイルを読んでいくループ */
  395:   while (!read_file(fp, &cur_input)) {
  396:     if (check_cond(&cond, &cur_input)) {
  397:       set_string(&cond, db, &cur_input, ac);
  398:     }
  399:   }
  400: 
  401:   anthy_release_context(ac);
  402:   anthy_quit();
  403: 
  404:   if (cond.ask) {
  405:     /* ユーザに聞く */
  406:     ask_results(db);
  407:   }
  408: 
  409:   show_stat(db);
  410:   save_db(expdata, db);
  411: 
  412:   return 0;
  413: }
Syntax (Markdown)