Subversion Repositories Kolibri OS

Rev

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

  1. #include <ctype.h>
  2. #include <inttypes.h>
  3. #include <stdbool.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7.  
  8. #include <libcss/libcss.h>
  9.  
  10. #include "utils/utils.h"
  11.  
  12. #include "dump.h"
  13. #include "testutils.h"
  14.  
  15. /** \todo at some point, we need to extend this to handle nested blocks */
  16. typedef struct line_ctx {
  17.         size_t buflen;
  18.         size_t bufused;
  19.         uint8_t *buf;
  20.  
  21.         size_t explen;
  22.         size_t expused;
  23.         char *exp;
  24.  
  25.         bool indata;
  26.         bool inerrors;
  27.         bool inexp;
  28.  
  29.         bool inrule;
  30. } line_ctx;
  31.  
  32. static bool handle_line(const char *data, size_t datalen, void *pw);
  33. static void css__parse_expected(line_ctx *ctx, const char *data, size_t len);
  34. static void run_test(const uint8_t *data, size_t len,
  35.                 const char *exp, size_t explen);
  36.  
  37. static void *myrealloc(void *data, size_t len, void *pw)
  38. {
  39.         UNUSED(pw);
  40.  
  41.         return realloc(data, len);
  42. }
  43.  
  44. static css_error resolve_url(void *pw,
  45.                 const char *base, lwc_string *rel, lwc_string **abs)
  46. {
  47.         UNUSED(pw);
  48.         UNUSED(base);
  49.  
  50.         /* About as useless as possible */
  51.         *abs = lwc_string_ref(rel);
  52.  
  53.         return CSS_OK;
  54. }
  55.  
  56. static bool fail_because_lwc_leaked = false;
  57.  
  58. static void
  59. printing_lwc_iterator(lwc_string *str, void *pw)
  60. {
  61.         UNUSED(pw);
  62.        
  63.         printf(" DICT: %*s\n", (int)(lwc_string_length(str)), lwc_string_data(str));
  64.         fail_because_lwc_leaked = true;
  65. }
  66.  
  67. int main(int argc, char **argv)
  68. {
  69.         line_ctx ctx;
  70.        
  71.         if (argc != 2) {
  72.                 printf("Usage: %s <filename>\n", argv[0]);
  73.                 return 1;
  74.         }
  75.  
  76.         ctx.buflen = css__parse_filesize(argv[1]);
  77.         if (ctx.buflen == 0)
  78.                 return 1;
  79.  
  80.         ctx.buf = malloc(ctx.buflen);
  81.         if (ctx.buf == NULL) {
  82.                 printf("Failed allocating %u bytes\n",
  83.                                 (unsigned int) ctx.buflen);
  84.                 return 1;
  85.         }
  86.  
  87.         ctx.buf[0] = '\0';
  88.         ctx.bufused = 0;
  89.         ctx.explen = 0;
  90.         ctx.expused = 0;
  91.         ctx.exp = NULL;
  92.         ctx.indata = false;
  93.         ctx.inerrors = false;
  94.         ctx.inexp = false;
  95.  
  96.         assert(css__parse_testfile(argv[1], handle_line, &ctx) == true);
  97.  
  98.         /* and run final test */
  99.         if (ctx.bufused > 0)
  100.                 run_test(ctx.buf, ctx.bufused, ctx.exp, ctx.expused);
  101.  
  102.         free(ctx.buf);
  103.         free(ctx.exp);
  104.  
  105.         lwc_iterate_strings(printing_lwc_iterator, NULL);
  106.        
  107.         assert(fail_because_lwc_leaked == false);
  108.        
  109.         printf("PASS\n");
  110.  
  111.         return 0;
  112. }
  113.  
  114. bool handle_line(const char *data, size_t datalen, void *pw)
  115. {
  116.         line_ctx *ctx = (line_ctx *) pw;
  117.  
  118.         if (data[0] == '#') {
  119.                 if (ctx->inexp) {
  120.                         /* This marks end of testcase, so run it */
  121.  
  122.                         run_test(ctx->buf, ctx->bufused,
  123.                                         ctx->exp, ctx->expused);
  124.  
  125.                         ctx->buf[0] = '\0';
  126.                         ctx->bufused = 0;
  127.  
  128.                         ctx->expused = 0;
  129.                 }
  130.  
  131.                 if (ctx->indata && strncasecmp(data+1, "errors", 6) == 0) {
  132.                         ctx->indata = false;
  133.                         ctx->inerrors = true;
  134.                         ctx->inexp = false;
  135.                 } else if (ctx->inerrors &&
  136.                                 strncasecmp(data+1, "expected", 8) == 0) {
  137.                         ctx->indata = false;
  138.                         ctx->inerrors = false;
  139.                         ctx->inexp = true;
  140.                         ctx->inrule = false;
  141.                 } else if (ctx->inexp && strncasecmp(data+1, "data", 4) == 0) {
  142.                         ctx->indata = true;
  143.                         ctx->inerrors = false;
  144.                         ctx->inexp = false;
  145.                 } else if (ctx->indata) {
  146.                         memcpy(ctx->buf + ctx->bufused, data, datalen);
  147.                         ctx->bufused += datalen;
  148.                 } else {
  149.                         ctx->indata = (strncasecmp(data+1, "data", 4) == 0);
  150.                         ctx->inerrors = (strncasecmp(data+1, "errors", 6) == 0);
  151.                         ctx->inexp = (strncasecmp(data+1, "expected", 8) == 0);
  152.                 }
  153.         } else {
  154.                 if (ctx->indata) {
  155.                         memcpy(ctx->buf + ctx->bufused, data, datalen);
  156.                         ctx->bufused += datalen;
  157.                 }
  158.                 if (ctx->inexp) {
  159.                         css__parse_expected(ctx, data, datalen);
  160.                 }
  161.         }
  162.  
  163.         return true;
  164. }
  165.  
  166. void css__parse_expected(line_ctx *ctx, const char *data, size_t len)
  167. {
  168.         while (ctx->expused + len >= ctx->explen) {
  169.                 size_t required = ctx->explen == 0 ? 64 : ctx->explen * 2;
  170.                 char *temp = realloc(ctx->exp, required);
  171.                 if (temp == NULL) {
  172.                         assert(0 && "No memory for expected output");
  173.                 }
  174.  
  175.                 ctx->exp = temp;
  176.                 ctx->explen = required;
  177.         }
  178.  
  179.         memcpy(ctx->exp + ctx->expused, data, len);
  180.  
  181.         ctx->expused += len;
  182. }
  183.  
  184. void run_test(const uint8_t *data, size_t len, const char *exp, size_t explen)
  185. {
  186.         css_stylesheet_params params;
  187.         css_stylesheet *sheet;
  188.         css_error error;
  189.         char *buf;
  190.         size_t buflen;
  191.         static int testnum;
  192.  
  193.         buf = malloc(2 * explen);
  194.         if (buf == NULL) {
  195.                 assert(0 && "No memory for result data");
  196.         }
  197.         buflen = 2 * explen;
  198.        
  199.         params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
  200.         params.level = CSS_LEVEL_21;
  201.         params.charset = "UTF-8";
  202.         params.url = "foo";
  203.         params.title = NULL;
  204.         params.allow_quirks = false;
  205.         params.inline_style = false;
  206.         params.resolve = resolve_url;
  207.         params.resolve_pw = NULL;
  208.         params.import = NULL;
  209.         params.import_pw = NULL;
  210.         params.color = NULL;
  211.         params.color_pw = NULL;
  212.         params.font = NULL;
  213.         params.font_pw = NULL;
  214.  
  215.         assert(css_stylesheet_create(&params, myrealloc, NULL,
  216.                         &sheet) == CSS_OK);
  217.  
  218.         error = css_stylesheet_append_data(sheet, data, len);
  219.         if (error != CSS_OK && error != CSS_NEEDDATA) {
  220.                 printf("Failed appending data: %d\n", error);
  221.                 assert(0);
  222.         }
  223.  
  224.         assert(css_stylesheet_data_done(sheet) == CSS_OK);
  225.  
  226.         testnum++;
  227.  
  228.         dump_sheet(sheet, buf, &buflen);
  229.  
  230.         if (2 * explen - buflen != explen || memcmp(buf, exp, explen) != 0) {
  231.                 printf("Expected (%u):\n%.*s\n",
  232.                                 (int) explen, (int) explen, exp);
  233.                 printf("Result (%u):\n%.*s\n", (int) (2 * explen - buflen),
  234.                         (int) (2 * explen - buflen), buf);
  235.                 assert(0 && "Result doesn't match expected");
  236.         }
  237.  
  238.         css_stylesheet_destroy(sheet);
  239.  
  240.         free(buf);
  241.  
  242.         printf("Test %d: PASS\n", testnum);
  243. }
  244.  
  245.