Source

nxjson / test.c

Full commit
/*
 * Copyright (c) 2013 Yaroslav Stavnichiy <yarosla@gmail.com>
 *
 * This file is part of NXJSON.
 *
 * NXJSON is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * NXJSON is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with NXJSON. If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#include "nxjson.h"

#define ERROR(msg, p) fprintf(stderr, "ERROR: " msg " %s\n", (p));

static char* load_file(const char* filepath) {
  struct stat st;
  if (stat(filepath, &st)==-1) {
    // ERROR("can't find file", filepath);
    return 0;
  }
  int fd=open(filepath, O_RDONLY);
  if (fd==-1) {
    ERROR("can't open file", filepath);
    return 0;
  }
  char* text=malloc(st.st_size+1); // this is not going to be freed
  if (st.st_size!=read(fd, text, st.st_size)) {
    ERROR("can't read file", filepath);
    close(fd);
    return 0;
  }
  close(fd);
  text[st.st_size]='\0';
  return text;
}

static int save_file(const char* filepath, const char* text) {
  int fd=open(filepath, O_WRONLY|O_CREAT|O_TRUNC, 0644);
  if (fd==-1) {
    ERROR("can't open file", filepath);
    return -1;
  }
  int length=strlen(text);
  if (length!=write(fd, text, length)) {
    ERROR("can't write file", filepath);
    close(fd);
    return -1;
  }
  close(fd);
  return 0;
}

static void dump(const nx_json* json, char* out, char** end, int indent) {
  if (!json) {
    *end=out;
    return;
  }
  int i;
  for (i=0; i<indent; i++) *out++=' ';
  if (json->key) {
    strcpy(out, json->key);
    out+=strlen(json->key);
    *out++=':';
  }
  switch (json->type) {
    case NX_JSON_NULL:
      strcpy(out, "null");
      out+=4;
      break;
    case NX_JSON_OBJECT:
      *out++='{';
      *out++='\n';
      {
        nx_json* js=json->child;
        for (js=json->child; js; js=js->next) {
          dump(js, out, &out, indent+2);
        }
      }
      for (i=0; i<indent; i++) *out++=' ';
      *out++='}';
      break;
    case NX_JSON_ARRAY:
      *out++='[';
      *out++='\n';
      {
        nx_json* js=json->child;
        for (js=json->child; js; js=js->next) {
          dump(js, out, &out, indent+2);
        }
      }
      for (i=0; i<indent; i++) *out++=' ';
      *out++=']';
      break;
    case NX_JSON_STRING:
      *out++='"';
      strcpy(out, json->text_value);
      out+=strlen(json->text_value);
      *out++='"';
      break;
    case NX_JSON_INTEGER:
      out+=sprintf(out, "%ld", json->int_value);
      break;
    case NX_JSON_DOUBLE:
      out+=sprintf(out, "%le", json->dbl_value);
      break;
    case NX_JSON_BOOL:
      *out++=json->int_value?'T':'F';
      break;
    default:
      strcpy(out, "????");
      out+=4;
      break;
  }
  *out++='\n';
  *end=out;
}

static int run_test(int test_number, char* input, const char* expected_output) {
  int input_length=strlen(input);
  const nx_json* json=nx_json_parse_utf8(input);
  if (!json) {
    if (!expected_output) {
      printf("[%03d] PASSED\n", test_number);
      return 1;
    }
    else {
      printf("[%03d] FAILED\n", test_number);
      return 0;
    }
  }
  char* buf=malloc(input_length*32+4000000); // hope this will be large enough; depends on nesting & indenting
  char* p=buf;
  dump(json, p, &p, 0);
  nx_json_free(json);
  *p='\0';

  char fname[32];
  sprintf(fname, "tests/%03d.result", test_number);
  save_file(fname, buf);

  if (!expected_output) {
    printf("[%03d] FAILED\n", test_number);
    free(buf);
    return 0;
  }
  if (!strcmp(buf, expected_output)) {
    printf("[%03d] PASSED\n", test_number);
    free(buf);
    return 1;
  }
  else {
    printf("[%03d] FAILED\n", test_number);
    free(buf);
    return 0;
  }
}

static void run_tests() {
  char infile[32];
  char expfile[32];
  int i, total=0, passed=0;
  for (i=1; i<100; i++) {
    sprintf(infile, "tests/%03d.json", i);
    sprintf(expfile, "tests/%03d.expected", i);
    char* input=load_file(infile);
    if (!input) break;
    char* expected_output=load_file(expfile);
    passed+=run_test(i, input, expected_output);
    total++;
    free(input);
    if (expected_output) free(expected_output);
  }
  printf("\nPASSED %d OUT OF %d\n", passed, total);
}

int main() {
  run_tests();
  return 0;
}