Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #include <ctype.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. #include <parserutils/charset/codec.h>
  6.  
  7. #include "utils/utils.h"
  8.  
  9. #include "testutils.h"
  10.  
  11. typedef struct line_ctx {
  12.         parserutils_charset_codec *codec;
  13.  
  14.         size_t buflen;
  15.         size_t bufused;
  16.         uint8_t *buf;
  17.         size_t explen;
  18.         size_t expused;
  19.         uint8_t *exp;
  20.  
  21.         bool hadenc;
  22.         bool indata;
  23.         bool inexp;
  24.  
  25.         parserutils_error exp_ret;
  26.  
  27.         enum { ENCODE, DECODE, BOTH } dir;
  28. } line_ctx;
  29.  
  30. static bool handle_line(const char *data, size_t datalen, void *pw);
  31. static void run_test(line_ctx *ctx);
  32.  
  33. static void *myrealloc(void *ptr, size_t len, void *pw)
  34. {
  35.         UNUSED(pw);
  36.  
  37.         return realloc(ptr, len);
  38. }
  39.  
  40. int main(int argc, char **argv)
  41. {
  42.         parserutils_charset_codec *codec;
  43.         line_ctx ctx;
  44.  
  45.         if (argc != 2) {
  46.                 printf("Usage: %s <filename>\n", argv[0]);
  47.                 return 1;
  48.         }
  49.  
  50.         assert(parserutils_charset_codec_create("NATS-SEFI-ADD",
  51.                         myrealloc, NULL, &codec) == PARSERUTILS_BADENCODING);
  52.  
  53.         ctx.buflen = parse_filesize(argv[1]);
  54.         if (ctx.buflen == 0)
  55.                 return 1;
  56.  
  57.         ctx.buf = malloc(2 * ctx.buflen);
  58.         if (ctx.buf == NULL) {
  59.                 printf("Failed allocating %u bytes\n",
  60.                                 (unsigned int) ctx.buflen);
  61.                 return 1;
  62.         }
  63.  
  64.         ctx.exp = ctx.buf + ctx.buflen;
  65.         ctx.explen = ctx.buflen;
  66.  
  67.         ctx.buf[0] = '\0';
  68.         ctx.exp[0] = '\0';
  69.         ctx.bufused = 0;
  70.         ctx.expused = 0;
  71.         ctx.hadenc = false;
  72.         ctx.indata = false;
  73.         ctx.inexp = false;
  74.         ctx.exp_ret = PARSERUTILS_OK;
  75.  
  76.         assert(parse_testfile(argv[1], handle_line, &ctx) == true);
  77.  
  78.         /* and run final test */
  79.         if (ctx.bufused > 0 && ctx.buf[ctx.bufused - 1] == '\n')
  80.                 ctx.bufused -= 1;
  81.  
  82.         if (ctx.expused > 0 && ctx.exp[ctx.expused - 1] == '\n')
  83.                 ctx.expused -= 1;
  84.  
  85.         run_test(&ctx);
  86.  
  87.         free(ctx.buf);
  88.  
  89.         parserutils_charset_codec_destroy(ctx.codec);
  90.  
  91.         printf("PASS\n");
  92.  
  93.         return 0;
  94. }
  95.  
  96. bool handle_line(const char *data, size_t datalen, void *pw)
  97. {
  98.         line_ctx *ctx = (line_ctx *) pw;
  99.  
  100.         if (data[0] == '#') {
  101.                 if (ctx->inexp) {
  102.                         /* This marks end of testcase, so run it */
  103.  
  104.                         if (ctx->buf[ctx->bufused - 1] == '\n')
  105.                                 ctx->bufused -= 1;
  106.  
  107.                         if (ctx->exp[ctx->expused - 1] == '\n')
  108.                                 ctx->expused -= 1;
  109.  
  110.                         run_test(ctx);
  111.  
  112.                         ctx->buf[0] = '\0';
  113.                         ctx->exp[0] = '\0';
  114.                         ctx->bufused = 0;
  115.                         ctx->expused = 0;
  116.                         ctx->exp_ret = PARSERUTILS_OK;
  117.                 }
  118.  
  119.                 if (strncasecmp(data+1, "data", 4) == 0) {
  120.                         parserutils_charset_codec_optparams params;
  121.                         const char *ptr = data + 6;
  122.  
  123.                         ctx->indata = true;
  124.                         ctx->inexp = false;
  125.  
  126.                         if (strncasecmp(ptr, "decode", 6) == 0)
  127.                                 ctx->dir = DECODE;
  128.                         else if (strncasecmp(ptr, "encode", 6) == 0)
  129.                                 ctx->dir = ENCODE;
  130.                         else
  131.                                 ctx->dir = BOTH;
  132.  
  133.                         ptr += 7;
  134.  
  135.                         if (strncasecmp(ptr, "LOOSE", 5) == 0) {
  136.                                 params.error_mode.mode =
  137.                                         PARSERUTILS_CHARSET_CODEC_ERROR_LOOSE;
  138.                                 ptr += 6;
  139.                         } else if (strncasecmp(ptr, "STRICT", 6) == 0) {
  140.                                 params.error_mode.mode =
  141.                                         PARSERUTILS_CHARSET_CODEC_ERROR_STRICT;
  142.                                 ptr += 7;
  143.                         } else {
  144.                                 params.error_mode.mode =
  145.                                         PARSERUTILS_CHARSET_CODEC_ERROR_TRANSLIT;
  146.                                 ptr += 9;
  147.                         }
  148.  
  149.                         assert(parserutils_charset_codec_setopt(ctx->codec,
  150.                                 PARSERUTILS_CHARSET_CODEC_ERROR_MODE,
  151.                                 (parserutils_charset_codec_optparams *) &params)
  152.                                 == PARSERUTILS_OK);
  153.                 } else if (strncasecmp(data+1, "expected", 8) == 0) {
  154.                         ctx->indata = false;
  155.                         ctx->inexp = true;
  156.  
  157.                         ctx->exp_ret = parserutils_error_from_string(data + 10,
  158.                                         datalen - 10 - 1 /* \n */);
  159.                 } else if (strncasecmp(data+1, "reset", 5) == 0) {
  160.                         ctx->indata = false;
  161.                         ctx->inexp = false;
  162.  
  163.                         parserutils_charset_codec_reset(ctx->codec);
  164.                 } else if (strncasecmp(data+1, "enc", 3) == 0) {
  165.                         const char *enc = data + 5;
  166.                         const char *end;
  167.                         char *enc_name;
  168.  
  169.                         for (end = enc; !isspace(*end); end++)
  170.                                 ;
  171.  
  172.                         enc_name = alloca(end - enc + 1);
  173.                         memcpy(enc_name, enc, end - enc);
  174.                         enc_name[end - enc] = 0;
  175.  
  176.                         assert(parserutils_charset_codec_create(enc_name,
  177.                                         myrealloc, NULL, &ctx->codec) ==
  178.                                         PARSERUTILS_OK);
  179.  
  180.                         ctx->hadenc = true;
  181.                 }
  182.         } else {
  183.                 if (ctx->indata) {
  184.                         memcpy(ctx->buf + ctx->bufused, data, datalen);
  185.                         ctx->bufused += datalen;
  186.                 }
  187.                 if (ctx->inexp) {
  188.                         memcpy(ctx->exp + ctx->expused, data, datalen);
  189.                         ctx->expused += datalen;
  190.                 }
  191.         }
  192.  
  193.         return true;
  194. }
  195.  
  196. void run_test(line_ctx *ctx)
  197. {
  198.         static int testnum;
  199.         size_t destlen = ctx->bufused * 4;
  200.         uint8_t *dest = alloca(destlen);
  201.         uint8_t *pdest = dest;
  202.         const uint8_t *psrc = ctx->buf;
  203.         size_t srclen = ctx->bufused;
  204.         size_t i;
  205.  
  206.         if (ctx->dir == DECODE) {
  207.                 assert(parserutils_charset_codec_decode(ctx->codec,
  208.                                 &psrc, &srclen,
  209.                                 &pdest, &destlen) == ctx->exp_ret);
  210.         } else if (ctx->dir == ENCODE) {
  211.                 assert(parserutils_charset_codec_encode(ctx->codec,
  212.                                 &psrc, &srclen,
  213.                                 &pdest, &destlen) == ctx->exp_ret);
  214.         } else {
  215.                 size_t templen = ctx->bufused * 4;
  216.                 uint8_t *temp = alloca(templen);
  217.                 uint8_t *ptemp = temp;
  218.                 const uint8_t *ptemp2;
  219.                 size_t templen2;
  220.  
  221.                 assert(parserutils_charset_codec_decode(ctx->codec,
  222.                                 &psrc, &srclen,
  223.                                 &ptemp, &templen) == ctx->exp_ret);
  224.                 /* \todo currently there is no way to specify the number of
  225.                    consumed & produced data in case of a deliberate bad input
  226.                    data set.  */
  227.                 if (ctx->exp_ret == PARSERUTILS_OK) {
  228.                         assert(temp + (ctx->bufused * 4 - templen) == ptemp);
  229.                 }
  230.  
  231.                 ptemp2 = temp;
  232.                 templen2 = ctx->bufused * 4 - templen;
  233.                 assert(parserutils_charset_codec_encode(ctx->codec,
  234.                                 &ptemp2, &templen2,
  235.                                 &pdest, &destlen) == ctx->exp_ret);
  236.                 if (ctx->exp_ret == PARSERUTILS_OK) {
  237.                         assert(templen2 == 0);
  238.                         assert(temp + (ctx->bufused * 4 - templen) == ptemp2);
  239.                 }
  240.         }
  241.         if (ctx->exp_ret == PARSERUTILS_OK) {
  242.                 assert(srclen == 0);
  243.                 assert(ctx->buf + ctx->bufused == psrc);
  244.                 assert(dest + (ctx->bufused * 4 - destlen) == pdest);
  245.                 assert(ctx->bufused * 4 - destlen == ctx->expused);
  246.         }
  247.  
  248.         printf("%d: Read '", ++testnum);
  249.         for (i = 0; i < ctx->expused; i++) {
  250.                 printf("%c%c ", "0123456789abcdef"[(dest[i] >> 4) & 0xf],
  251.                                 "0123456789abcdef"[dest[i] & 0xf]);
  252.         }
  253.         printf("' Expected '");
  254.         for (i = 0; i < ctx->expused; i++) {
  255.                 printf("%c%c ", "0123456789abcdef"[(ctx->exp[i] >> 4) & 0xf],
  256.                                 "0123456789abcdef"[ctx->exp[i] & 0xf]);
  257.         }
  258.         printf("'\n");
  259.  
  260.         assert(pdest == dest + ctx->expused);
  261.         assert(memcmp(dest, ctx->exp, ctx->expused) == 0);
  262. }
  263.  
  264.