Subversion Repositories Kolibri OS

Rev

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

  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. #include <parserutils/charset/codec.h>
  5.  
  6. #include "utils/utils.h"
  7.  
  8. #include "testutils.h"
  9.  
  10. typedef struct line_ctx {
  11.         parserutils_charset_codec *codec;
  12.  
  13.         size_t buflen;
  14.         size_t bufused;
  15.         uint8_t *buf;
  16.         size_t explen;
  17.         size_t expused;
  18.         uint8_t *exp;
  19.  
  20.         bool indata;
  21.         bool inexp;
  22.  
  23.         parserutils_error exp_ret;
  24.  
  25.         enum { ENCODE, DECODE, BOTH } dir;
  26. } line_ctx;
  27.  
  28. static bool handle_line(const char *data, size_t datalen, void *pw);
  29. static void run_test(line_ctx *ctx);
  30.  
  31. static void *myrealloc(void *ptr, size_t len, void *pw)
  32. {
  33.         UNUSED(pw);
  34.  
  35.         return realloc(ptr, len);
  36. }
  37.  
  38. int main(int argc, char **argv)
  39. {
  40.         parserutils_charset_codec *codec;
  41.         line_ctx ctx;
  42.  
  43.         if (argc != 2) {
  44.                 printf("Usage: %s <filename>\n", argv[0]);
  45.                 return 1;
  46.         }
  47.  
  48.         assert(parserutils_charset_codec_create("NATS-SEFI-ADD",
  49.                         myrealloc, NULL, &codec) == PARSERUTILS_BADENCODING);
  50.  
  51.         assert(parserutils_charset_codec_create("UTF-8", myrealloc, NULL,
  52.                         &ctx.codec) == PARSERUTILS_OK);
  53.  
  54.         ctx.buflen = parse_filesize(argv[1]);
  55.         if (ctx.buflen == 0)
  56.                 return 1;
  57.  
  58.         ctx.buf = malloc(2 * ctx.buflen);
  59.         if (ctx.buf == NULL) {
  60.                 printf("Failed allocating %u bytes\n",
  61.                                 (unsigned int) ctx.buflen);
  62.                 return 1;
  63.         }
  64.  
  65.         ctx.exp = ctx.buf + ctx.buflen;
  66.         ctx.explen = ctx.buflen;
  67.  
  68.         ctx.buf[0] = '\0';
  69.         ctx.exp[0] = '\0';
  70.         ctx.bufused = 0;
  71.         ctx.expused = 0;
  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.                 }
  165.         } else {
  166.                 if (ctx->indata) {
  167.                         memcpy(ctx->buf + ctx->bufused, data, datalen);
  168.                         ctx->bufused += datalen;
  169.                 }
  170.                 if (ctx->inexp) {
  171.                         memcpy(ctx->exp + ctx->expused, data, datalen);
  172.                         ctx->expused += datalen;
  173.                 }
  174.         }
  175.  
  176.         return true;
  177. }
  178.  
  179. void run_test(line_ctx *ctx)
  180. {
  181.         static int testnum;
  182.         size_t destlen = ctx->bufused * 4;
  183.         uint8_t *dest = alloca(destlen);
  184.         uint8_t *pdest = dest;
  185.         const uint8_t *psrc = ctx->buf;
  186.         size_t srclen = ctx->bufused;
  187.         size_t i;
  188.  
  189.         if (ctx->dir == DECODE) {
  190.                 assert(parserutils_charset_codec_decode(ctx->codec,
  191.                                 &psrc, &srclen,
  192.                                 &pdest, &destlen) == ctx->exp_ret);
  193.         } else if (ctx->dir == ENCODE) {
  194.                 assert(parserutils_charset_codec_encode(ctx->codec,
  195.                                 &psrc, &srclen,
  196.                                 &pdest, &destlen) == ctx->exp_ret);
  197.         } else {
  198.                 size_t templen = ctx->bufused * 4;
  199.                 uint8_t *temp = alloca(templen);
  200.                 uint8_t *ptemp = temp;
  201.                 const uint8_t *ptemp2;
  202.                 size_t templen2;
  203.  
  204.                 assert(parserutils_charset_codec_decode(ctx->codec,
  205.                                 &psrc, &srclen,
  206.                                 &ptemp, &templen) == ctx->exp_ret);
  207.                 /* \todo currently there is no way to specify the number of
  208.                    consumed & produced data in case of a deliberate bad input
  209.                    data set.  */
  210.                 if (ctx->exp_ret == PARSERUTILS_OK) {
  211.                         assert(temp + (ctx->bufused * 4 - templen) == ptemp);
  212.                 }
  213.  
  214.                 ptemp2 = temp;
  215.                 templen2 = ctx->bufused * 4 - templen;
  216.                 assert(parserutils_charset_codec_encode(ctx->codec,
  217.                                 &ptemp2, &templen2,
  218.                                 &pdest, &destlen) == ctx->exp_ret);
  219.                 if (ctx->exp_ret == PARSERUTILS_OK) {
  220.                         assert(templen2 == 0);
  221.                         assert(temp + (ctx->bufused * 4 - templen) == ptemp2);
  222.                 }
  223.         }
  224.         if (ctx->exp_ret == PARSERUTILS_OK) {
  225.                 assert(srclen == 0);
  226.                 assert(ctx->buf + ctx->bufused == psrc);
  227.                 assert(dest + (ctx->bufused * 4 - destlen) == pdest);
  228.                 assert(ctx->bufused * 4 - destlen == ctx->expused);
  229.         }
  230.  
  231.         printf("%d: Read '", ++testnum);
  232.         for (i = 0; i < ctx->expused; i++) {
  233.                 printf("%c%c ", "0123456789abcdef"[(dest[i] >> 4) & 0xf],
  234.                                 "0123456789abcdef"[dest[i] & 0xf]);
  235.         }
  236.         printf("' Expected '");
  237.         for (i = 0; i < ctx->expused; i++) {
  238.                 printf("%c%c ", "0123456789abcdef"[(ctx->exp[i] >> 4) & 0xf],
  239.                                 "0123456789abcdef"[ctx->exp[i] & 0xf]);
  240.         }
  241.         printf("'\n");
  242.  
  243.         assert(pdest == dest + ctx->expused);
  244.         assert(memcmp(dest, ctx->exp, ctx->expused) == 0);
  245. }
  246.  
  247.