Home | History | Annotate | Download | only in test
      1 #include <unistd.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <sys/stat.h>
      5 #include <fcntl.h>
      6 #include <string.h>
      7 
      8 #include "cn-cbor/cn-cbor.h"
      9 
     10 #ifdef USE_CBOR_CONTEXT
     11 #define CBOR_CONTEXT_PARAM , NULL
     12 #else
     13 #define CBOR_CONTEXT_PARAM
     14 #endif
     15 
     16 #define ERROR(msg, p) fprintf(stderr, "ERROR: " msg " %s\n", (p));
     17 
     18 static unsigned char* load_file(const char* filepath, unsigned char **end) {
     19   struct stat st;
     20   if (stat(filepath, &st)==-1) {
     21     ERROR("can't find file", filepath);
     22     return 0;
     23   }
     24   int fd=open(filepath, O_RDONLY);
     25   if (fd==-1) {
     26     ERROR("can't open file", filepath);
     27     return 0;
     28   }
     29   unsigned char* text=malloc(st.st_size+1); // this is not going to be freed
     30   if (st.st_size!=read(fd, text, st.st_size)) {
     31     ERROR("can't read file", filepath);
     32     close(fd);
     33     return 0;
     34   }
     35   close(fd);
     36   text[st.st_size]='\0';
     37   *end = text + st.st_size;
     38   return text;
     39 }
     40 
     41 static void dump(const cn_cbor* cb, char* out, char** end, int indent) {
     42   if (!cb)
     43     goto done;
     44   int i;
     45   cn_cbor* cp;
     46   char finchar = ')';           /* most likely */
     47 
     48 #define CPY(s, l) memcpy(out, s, l); out += l;
     49 #define OUT(s) CPY(s, sizeof(s)-1)
     50 #define PRF(f, a) out += sprintf(out, f, a)
     51 
     52   for (i = 0; i < indent; i++) *out++ = ' ';
     53   switch (cb->type) {
     54   case CN_CBOR_TEXT_CHUNKED:   OUT("(_\n");                  goto sequence;
     55   case CN_CBOR_BYTES_CHUNKED:  OUT("(_\n\n");                goto sequence;
     56   case CN_CBOR_TAG:            PRF("%ld(\n", cb->v.sint);    goto sequence;
     57   case CN_CBOR_ARRAY:  finchar = ']'; OUT("[\n");            goto sequence;
     58   case CN_CBOR_MAP:    finchar = '}'; OUT("{\n");            goto sequence;
     59   sequence:
     60     for (cp = cb->first_child; cp; cp = cp->next) {
     61       dump(cp, out, &out, indent+2);
     62     }
     63     for (i=0; i<indent; i++) *out++ = ' ';
     64     *out++ = finchar;
     65     break;
     66   case CN_CBOR_BYTES:   OUT("h'");
     67     for (i=0; i<cb->length; i++)
     68       PRF("%02x", cb->v.str[i] & 0xff);
     69     *out++ = '\'';
     70     break;
     71   case CN_CBOR_TEXT:    *out++ = '"';
     72     CPY(cb->v.str, cb->length); /* should escape stuff */
     73     *out++ = '"';
     74     break;
     75   case CN_CBOR_NULL:   OUT("null");                      break;
     76   case CN_CBOR_TRUE:   OUT("true");                      break;
     77   case CN_CBOR_FALSE:  OUT("false");                     break;
     78   case CN_CBOR_UNDEF:  OUT("simple(23)");                break;
     79   case CN_CBOR_INT:    PRF("%ld", cb->v.sint);           break;
     80   case CN_CBOR_UINT:   PRF("%lu", cb->v.uint);           break;
     81   case CN_CBOR_DOUBLE: PRF("%e", cb->v.dbl);             break;
     82   case CN_CBOR_SIMPLE: PRF("simple(%ld)", cb->v.sint);   break;
     83   default:             PRF("???%d???", cb->type);        break;
     84   }
     85   *out++ = '\n';
     86 done:
     87   *end = out;
     88 }
     89 
     90 
     91 const char *err_name[] = {
     92   "CN_CBOR_NO_ERROR",
     93   "CN_CBOR_ERR_OUT_OF_DATA",
     94   "CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED",
     95   "CN_CBOR_ERR_ODD_SIZE_INDEF_MAP",
     96   "CN_CBOR_ERR_BREAK_OUTSIDE_INDEF",
     97   "CN_CBOR_ERR_MT_UNDEF_FOR_INDEF",
     98   "CN_CBOR_ERR_RESERVED_AI",
     99   "CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING",
    100   "CN_CBOR_ERR_OUT_OF_MEMORY",
    101   "CN_CBOR_ERR_FLOAT_NOT_SUPPORTED",
    102 };
    103 
    104 static void cn_cbor_decode_test(const unsigned char *buf, int len) {
    105   struct cn_cbor_errback back;
    106   const cn_cbor *ret = cn_cbor_decode(buf, len CBOR_CONTEXT_PARAM, &back);
    107   if (ret)
    108     printf("oops 1");
    109   printf("%s at %d\n", err_name[back.err], back.pos);
    110 }
    111 
    112 int main() {
    113   char buf[100000];
    114   unsigned char *end;
    115   char *bufend;
    116   unsigned char *s = load_file("cases.cbor", &end);
    117   printf("%zd\n", end-s);
    118   cn_cbor *cb = cn_cbor_decode(s, end-s CBOR_CONTEXT_PARAM, 0);
    119   if (cb) {
    120     dump(cb, buf, &bufend, 0);
    121     *bufend = 0;
    122     printf("%s\n", buf);
    123     cn_cbor_free(cb CBOR_CONTEXT_PARAM);
    124     cb = 0;                     /* for leaks testing */
    125   }
    126   cn_cbor_decode_test((const unsigned char*)"\xff", 1);    /* break outside indef */
    127   cn_cbor_decode_test((const unsigned char*)"\x1f", 1);    /* mt undef for indef */
    128   cn_cbor_decode_test((const unsigned char*)"\x00\x00", 2);    /* not all data consumed */
    129   cn_cbor_decode_test((const unsigned char*)"\x81", 1);    /* out of data */
    130   cn_cbor_decode_test((const unsigned char*)"\x1c", 1);    /* reserved ai */
    131   cn_cbor_decode_test((const unsigned char*)"\xbf\x00\xff", 3);    /* odd size indef map */
    132   cn_cbor_decode_test((const unsigned char*)"\x7f\x40\xff", 3);    /* wrong nesting in indef string */
    133   system("leaks test");
    134 }
    135 
    136 /* cn-cbor.c:112:    CN_CBOR_FAIL("out of memory"); */
    137