Skip to content
Snippets Groups Projects
test_json.c 54.5 KiB
Newer Older
  • Learn to ignore specific revisions
  • David M. Lee's avatar
    David M. Lee committed
    AST_TEST_DEFINE(json_test_object_iter)
    {
    	struct ast_json_iter *iter;
    	int count;
    	int uut_res;
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "object_iter";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing iterating through JSON objects.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* Object iterator testing */
    	uut = ast_json_pack("{s: i, s: i, s: i, s: i, s: i}", "one", 1, "two", 2, "three", 3, "four", 4, "five", 5);
    
    	/* Iterate through the object; be aware that order isn't specified */
    	iter = ast_json_object_iter(uut);
    	ast_test_validate(test, NULL != iter);
    	count = 0;
    	while (NULL != iter) {
    		if (0 == strcmp("one", ast_json_object_iter_key(iter))) {
    			ast_test_validate(test, 1 == ast_json_integer_get(ast_json_object_iter_value(iter)));
    		} else if (0 == strcmp("two", ast_json_object_iter_key(iter))) {
    			ast_test_validate(test, 2 == ast_json_integer_get(ast_json_object_iter_value(iter)));
    		} else if (0 == strcmp("three", ast_json_object_iter_key(iter))) {
    			ast_test_validate(test, 3 == ast_json_integer_get(ast_json_object_iter_value(iter)));
    		} else if (0 == strcmp("four", ast_json_object_iter_key(iter))) {
    			ast_test_validate(test, 4 == ast_json_integer_get(ast_json_object_iter_value(iter)));
    		} else if (0 == strcmp("five", ast_json_object_iter_key(iter))) {
    			ast_test_validate(test, 5 == ast_json_integer_get(ast_json_object_iter_value(iter)));
    		} else {
    			/* Unexpected key */
    			ast_test_validate(test, 0);
    		}
    		iter = ast_json_object_iter_next(uut, iter);
    		++count;
    	}
    	ast_test_validate(test, 5 == count);
    
    	/* iterator non-existing key */
    	iter = ast_json_object_iter_at(uut, "dne");
    	ast_test_validate(test, NULL == iter);
    
    	/* iterator specific key */
    	iter = ast_json_object_iter_at(uut, "three");
    	ast_test_validate(test, NULL != iter);
    	ast_test_validate(test, 3 == ast_json_integer_get(ast_json_object_iter_value(iter)));
    
    	/* set via iter */
    	iter = ast_json_object_iter_at(uut, "three");
    	uut_res = ast_json_object_iter_set(uut, iter, ast_json_integer_create(-3));
    	ast_test_validate(test, 0 == uut_res);
    	ast_test_validate(test, -3 == ast_json_integer_get(ast_json_object_get(uut, "three")));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_object_iter_null)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "object_iter_null";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing JSON object iterator NULL testings.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* iterator NULL tests */
    	uut = ast_json_object_create();
    	ast_test_validate(test, NULL == ast_json_object_iter(NULL));
    	ast_test_validate(test, NULL == ast_json_object_iter_at(NULL, "not null"));
    	ast_test_validate(test, NULL == ast_json_object_iter_next(NULL, NULL));
    	ast_test_validate(test, NULL == ast_json_object_iter_next(uut, NULL));
    	ast_test_validate(test, NULL == ast_json_object_iter_key(NULL));
    	ast_test_validate(test, NULL == ast_json_object_iter_value(NULL));
    	ast_test_validate(test, -1 == ast_json_object_iter_set(NULL, NULL, ast_json_null()));
    	ast_test_validate(test, -1 == ast_json_object_iter_set(uut, NULL, ast_json_null()));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_dump_load_string)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    	RAII_VAR(char *, str, NULL, json_debug_free);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "dump_load_string";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing dumping strings from JSON.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    	expected = ast_json_pack("{ s: i }", "one", 1);
    	str = ast_json_dump_string(expected);
    	ast_test_validate(test, NULL != str);
    	uut = ast_json_load_string(str, NULL);
    	ast_test_validate(test, NULL != uut);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	/* dump_string NULL */
    	ast_test_validate(test, NULL == ast_json_dump_string(NULL));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_dump_load_str)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    	RAII_VAR(struct ast_str *, astr, NULL, ast_free);
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "dump_load_str";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing dumping ast_str from JSON.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* dump/load ast_str */
    	expected = ast_json_pack("{ s: i }", "one", 1);
    	astr = ast_str_create(1); /* should expand to hold output */
    	uut_res = ast_json_dump_str(expected, &astr);
    	ast_test_validate(test, 0 == uut_res);
    	uut = ast_json_load_str(astr, NULL);
    	ast_test_validate(test, NULL != uut);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_dump_str_fail)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    	struct ast_str *astr;
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "dump_str_fail";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing dumping to ast_str when it can't grow.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* dump ast_str growth failure */
    	expected = ast_json_pack("{ s: i }", "one", 1);
    	astr = ast_str_alloca(1); /* cannot grow */
    	uut_res = ast_json_dump_str(expected, &astr);
    	ast_test_validate(test, 0 != uut_res);
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_load_buffer)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	const char *str;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "load_buffer";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing loading JSON from buffer.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* load buffer */
    	str = "{ \"one\": 1 } trailing garbage";
    	uut = ast_json_load_string(str, NULL);
    	ast_test_validate(test, NULL == uut);
    	uut = ast_json_load_buf(str, strlen("{ \"one\": 1 }"), NULL);
    	ast_test_validate(test, NULL != uut);
    
    	return AST_TEST_PASS;
    }
    
    /*! \brief \a fclose isn't NULL safe. */
    static int safe_fclose(FILE *f)
    {
    	if (f) {
    		return fclose(f);
    	}
    	return 0;
    }
    
    
    static FILE *mkstemp_file(char *template, const char *mode)
    {
    	int fd = mkstemp(template);
    	FILE *file;
    
    	if (fd < 0) {
    		ast_log(LOG_ERROR, "Failed to create temp file: %s\n",
    			strerror(errno));
    		return NULL;
    	}
    
    	file = fdopen(fd, mode);
    	if (!file) {
    		ast_log(LOG_ERROR, "Failed to create temp file: %s\n",
    			strerror(errno));
    		return NULL;
    	}
    
    	return file;
    }
    
    
    David M. Lee's avatar
    David M. Lee committed
    AST_TEST_DEFINE(json_test_dump_load_file)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    
    	char filename[] = "/tmp/ast_json.XXXXXX";
    	RAII_VAR(char *, rm_on_exit, filename, unlink);
    
    David M. Lee's avatar
    David M. Lee committed
    	RAII_VAR(FILE *, file, NULL, safe_fclose);
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "dump_load_file";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing dumping/loading JSON to/from file by FILE *.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* dump/load file */
    	expected = ast_json_pack("{ s: i }", "one", 1);
    
    	file = mkstemp_file(filename, "w");
    	ast_test_validate(test, NULL != file);
    
    David M. Lee's avatar
    David M. Lee committed
    	uut_res = ast_json_dump_file(expected, file);
    	ast_test_validate(test, 0 == uut_res);
    	fclose(file);
    	file = fopen(filename, "r");
    
    	ast_test_validate(test, NULL != file);
    
    David M. Lee's avatar
    David M. Lee committed
    	uut = ast_json_load_file(file, NULL);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_dump_load_new_file)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    
    	char filename[] = "/tmp/ast_json.XXXXXX";
    	RAII_VAR(char *, rm_on_exit, filename, unlink);
    	RAII_VAR(FILE *, file, NULL, safe_fclose);
    
    David M. Lee's avatar
    David M. Lee committed
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "dump_load_new_file";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing dumping/load JSON to/from file by filename.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* dump/load filename */
    	expected = ast_json_pack("{ s: i }", "one", 1);
    
    	file = mkstemp_file(filename, "w");
    	ast_test_validate(test, NULL != file);
    
    David M. Lee's avatar
    David M. Lee committed
    	uut_res = ast_json_dump_new_file(expected, filename);
    	ast_test_validate(test, 0 == uut_res);
    	uut = ast_json_load_new_file(filename, NULL);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_dump_load_null)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    
    	char filename[] = "/tmp/ast_json.XXXXXX";
    	RAII_VAR(char *, rm_on_exit, filename, unlink);
    
    David M. Lee's avatar
    David M. Lee committed
    	RAII_VAR(FILE *, file, NULL, safe_fclose);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "dump_load_null";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing NULL handling of dump/load functions.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* dump/load NULL tests */
    	uut = ast_json_load_string("{ \"one\": 1 }", NULL);
    	ast_test_validate(test, NULL != uut);
    
    	file = mkstemp_file(filename, "w");
    	ast_test_validate(test, NULL != file);
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_test_validate(test, NULL == ast_json_dump_string(NULL));
    	ast_test_validate(test, -1 == ast_json_dump_file(NULL, file));
    	ast_test_validate(test, -1 == ast_json_dump_file(uut, NULL));
    	ast_test_validate(test, -1 == ast_json_dump_file(NULL, NULL));
    	ast_test_validate(test, -1 == ast_json_dump_new_file(uut, NULL));
    	ast_test_validate(test, -1 == ast_json_dump_new_file(NULL, filename));
    	ast_test_validate(test, -1 == ast_json_dump_new_file(NULL, NULL));
    	ast_test_validate(test, NULL == ast_json_load_string(NULL, NULL));
    	ast_test_validate(test, NULL == ast_json_load_buf(NULL, 0, NULL));
    	ast_test_validate(test, NULL == ast_json_load_file(NULL, NULL));
    	ast_test_validate(test, NULL == ast_json_load_new_file(NULL, NULL));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_parse_errors)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "parse_errors";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing various parse errors.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* parse errors */
    	ast_test_validate(test, NULL == ast_json_load_string("'singleton'", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("{ no value }", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("{ 'no': 'curly' ", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("[ 'no', 'square'", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("{ 1: 'int key' }", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("{ 'missing' 'colon' }", NULL));
    	ast_test_validate(test, NULL == ast_json_load_string("[ 'missing' 'comma' ]", NULL));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_pack)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "pack";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing json_pack function.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* pack test */
    	expected = ast_json_array_create();
    	ast_json_array_append(expected, ast_json_array_create());
    	ast_json_array_append(expected, ast_json_object_create());
    	ast_json_array_append(ast_json_array_get(expected, 0), ast_json_integer_create(1));
    	ast_json_array_append(ast_json_array_get(expected, 0), ast_json_integer_create(2));
    	ast_json_object_set(ast_json_array_get(expected, 1), "cool", ast_json_true());
    	uut = ast_json_pack("[[i,i],{s:b}]", 1, 2, "cool", 1);
    	ast_test_validate(test, NULL != uut);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    
    AST_TEST_DEFINE(json_test_pack_ownership)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "pack_ownership";
    
    		info->category = CATEGORY;
    
    		info->summary = "Testing json_pack failure conditions.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	uut = ast_json_pack("[o]", ast_json_string_create("Am I freed?"));
    
    	return AST_TEST_PASS;
    }
    
    
    David M. Lee's avatar
    David M. Lee committed
    AST_TEST_DEFINE(json_test_pack_errors)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "object_alloc";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing json_pack failure conditions.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* pack errors */
    	ast_test_validate(test, NULL == ast_json_pack(NULL));
    	ast_test_validate(test, NULL == ast_json_pack("{s:i", "no curly", 911));
    	ast_test_validate(test, NULL == ast_json_pack("[s, s", "no", "square"));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_copy)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "copy";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing copying JSON.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* copy test */
    	expected = ast_json_pack("{s: {s: i}}", "outer", "inner", 8675309);
    	uut = ast_json_copy(expected);
    	ast_test_validate(test, NULL != uut);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    	ast_test_validate(test, ast_json_object_get(expected, "outer") == ast_json_object_get(uut, "outer"));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_deep_copy)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "deep_copy";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing deep copying of JSON.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* deep copy test */
    	expected = ast_json_pack("{s: {s: i}}", "outer", "inner", 8675309);
    	uut = ast_json_deep_copy(expected);
    	ast_test_validate(test, NULL != uut);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    	ast_test_validate(test, ast_json_object_get(expected, "outer") != ast_json_object_get(uut, "outer"));
    	/* Changing the inner value of one should not change the other */
    	ast_json_integer_set(ast_json_object_get(ast_json_object_get(uut, "outer"), "inner"), 411);
    	ast_test_validate(test, !ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_copy_null)
    {
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "copy_null";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Testing NULL handling of copy functions.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* copy NULL */
    	ast_test_validate(test, NULL == ast_json_copy(NULL));
    	ast_test_validate(test, NULL == ast_json_deep_copy(NULL));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_circular_object)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "circular_object";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Object cannot be added to itself.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* circular reference testing */
    	/* Cannot add self */
    	uut = ast_json_object_create();
    
    	uut_res = ast_json_object_set(uut, "myself", ast_json_ref(uut));
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_test_validate(test, -1 == uut_res);
    	ast_test_validate(test, 0 == ast_json_object_size(uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_circular_array)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "circular_array";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "Array cannot be added to itself.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	uut = ast_json_array_create();
    
    	ast_test_validate(test, 0 == ast_json_array_size(uut));
    	uut_res = ast_json_array_append(uut, ast_json_ref(uut));
    
    David M. Lee's avatar
    David M. Lee committed
    	ast_test_validate(test, -1 == uut_res);
    	ast_test_validate(test, 0 == ast_json_array_size(uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_clever_circle)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, inner_child, NULL, ast_json_unref);
    	RAII_VAR(char *, str, NULL, json_debug_free);
    	int uut_res;
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "clever_circle";
    
    		info->category = CATEGORY;
    
    David M. Lee's avatar
    David M. Lee committed
    		info->summary = "JSON with circular references cannot be encoded.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	/* can add to self if you're clever enough, but it should not encode */
    	uut = ast_json_object_create();
    	inner_child = ast_json_object_create();
    	uut_res = ast_json_object_set(uut, "inner_child", ast_json_ref(inner_child));   /* incref to keep a reference */
    	ast_test_validate(test, 0 == uut_res);
    	uut_res = ast_json_object_set(inner_child, "parent", ast_json_ref(uut));   /* incref to keep a reference */
    	ast_test_validate(test, 0 == uut_res);
    	str = ast_json_dump_string(uut);
    	ast_test_validate(test, NULL == str);
    	/* Circular refs screw up reference counting, so break the cycle */
    	ast_json_object_clear(inner_child);
    
    	return AST_TEST_PASS;
    }
    
    
    static int test_name_number(const char *name, const char *number)
    
    	int res;
    	struct ast_json *uut;
    	struct ast_json *expected;
    
    	expected = ast_json_pack("{s: s, s: s}",
    		"name", name ?: "",
    		"number", number ?: "");
    	uut = ast_json_name_number(name, number);
    
    	res = ast_json_equal(expected, uut);
    
    	ast_json_unref(expected);
    	ast_json_unref(uut);
    	return res;
    }
    
    AST_TEST_DEFINE(json_test_name_number)
    {
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "name_number";
    
    		info->category = CATEGORY;
    
    		info->summary = "JSON encoding of name/number pair.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    
    	ast_test_validate(test, test_name_number("name", NULL));
    	ast_test_validate(test, test_name_number(NULL, "1234"));
    	ast_test_validate(test, test_name_number(NULL, NULL));
    	ast_test_validate(test, test_name_number("Jenny", "867-5309"));
    
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_timeval)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    	struct timeval tv = {};
    
    	switch (cmd) {
    	case TEST_INIT:
    
    		info->name = "type_timeval";
    
    		info->category = CATEGORY;
    
    		info->summary = "JSON encoding of timevals.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	expected = ast_json_string_create("2013-02-07T09:32:34.314-0600");
    
    	tv.tv_sec = 1360251154;
    	tv.tv_usec = 314159;
    
    	uut = ast_json_timeval(tv, "America/Chicago");
    
    
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    AST_TEST_DEFINE(json_test_cep)
    {
    	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
    	RAII_VAR(struct ast_json *, expected, NULL, ast_json_unref);
    
    	switch (cmd) {
    	case TEST_INIT:
    		info->name = "cep";
    
    		info->category = CATEGORY;
    
    		info->summary = "JSON with circular references cannot be encoded.";
    		info->description = "Test JSON abstraction library.";
    		return AST_TEST_NOT_RUN;
    	case TEST_EXECUTE:
    		break;
    	}
    
    	expected = ast_json_pack("{s: o, s: o, s: o}",
    				 "context", ast_json_null(),
    				 "exten", ast_json_null(),
    				 "priority", ast_json_null());
    	uut = ast_json_dialplan_cep(NULL, NULL, -1);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	ast_json_unref(expected);
    	ast_json_unref(uut);
    	expected = ast_json_pack("{s: s, s: s, s: i}",
    				 "context", "main",
    				 "exten", "4321",
    				 "priority", 7);
    	uut = ast_json_dialplan_cep("main", "4321", 7);
    	ast_test_validate(test, ast_json_equal(expected, uut));
    
    	return AST_TEST_PASS;
    }
    
    
    David M. Lee's avatar
    David M. Lee committed
    static int unload_module(void)
    {
    	AST_TEST_UNREGISTER(json_test_false);
    	AST_TEST_UNREGISTER(json_test_true);
    	AST_TEST_UNREGISTER(json_test_bool0);
    	AST_TEST_UNREGISTER(json_test_bool1);
    	AST_TEST_UNREGISTER(json_test_null);
    	AST_TEST_UNREGISTER(json_test_null_val);
    	AST_TEST_UNREGISTER(json_test_string);
    	AST_TEST_UNREGISTER(json_test_string_null);
    	AST_TEST_UNREGISTER(json_test_stringf);
    	AST_TEST_UNREGISTER(json_test_int);
    	AST_TEST_UNREGISTER(json_test_non_int);
    	AST_TEST_UNREGISTER(json_test_array_create);
    	AST_TEST_UNREGISTER(json_test_array_append);
    	AST_TEST_UNREGISTER(json_test_array_inset);
    	AST_TEST_UNREGISTER(json_test_array_set);
    	AST_TEST_UNREGISTER(json_test_array_remove);
    	AST_TEST_UNREGISTER(json_test_array_clear);
    	AST_TEST_UNREGISTER(json_test_array_extend);
    	AST_TEST_UNREGISTER(json_test_array_null);
    	AST_TEST_UNREGISTER(json_test_object_alloc);
    	AST_TEST_UNREGISTER(json_test_object_set);
    	AST_TEST_UNREGISTER(json_test_object_set_overwrite);
    	AST_TEST_UNREGISTER(json_test_object_get);
    	AST_TEST_UNREGISTER(json_test_object_del);
    	AST_TEST_UNREGISTER(json_test_object_clear);
    	AST_TEST_UNREGISTER(json_test_object_merge_all);
    	AST_TEST_UNREGISTER(json_test_object_merge_existing);
    	AST_TEST_UNREGISTER(json_test_object_merge_missing);
    	AST_TEST_UNREGISTER(json_test_object_null);
    	AST_TEST_UNREGISTER(json_test_object_iter);
    	AST_TEST_UNREGISTER(json_test_object_iter_null);
    	AST_TEST_UNREGISTER(json_test_dump_load_string);
    	AST_TEST_UNREGISTER(json_test_dump_load_str);
    	AST_TEST_UNREGISTER(json_test_dump_str_fail);
    	AST_TEST_UNREGISTER(json_test_load_buffer);
    	AST_TEST_UNREGISTER(json_test_dump_load_file);
    	AST_TEST_UNREGISTER(json_test_dump_load_new_file);
    	AST_TEST_UNREGISTER(json_test_dump_load_null);
    	AST_TEST_UNREGISTER(json_test_parse_errors);
    	AST_TEST_UNREGISTER(json_test_pack);
    
    	AST_TEST_UNREGISTER(json_test_pack_ownership);
    
    David M. Lee's avatar
    David M. Lee committed
    	AST_TEST_UNREGISTER(json_test_pack_errors);
    	AST_TEST_UNREGISTER(json_test_copy);
    	AST_TEST_UNREGISTER(json_test_deep_copy);
    	AST_TEST_UNREGISTER(json_test_copy_null);
    	AST_TEST_UNREGISTER(json_test_circular_object);
    	AST_TEST_UNREGISTER(json_test_circular_array);
    	AST_TEST_UNREGISTER(json_test_clever_circle);
    
    	AST_TEST_UNREGISTER(json_test_name_number);
    	AST_TEST_UNREGISTER(json_test_timeval);
    	AST_TEST_UNREGISTER(json_test_cep);
    
    David M. Lee's avatar
    David M. Lee committed
    	return 0;
    }
    
    static int load_module(void)
    {
    	AST_TEST_REGISTER(json_test_false);
    	AST_TEST_REGISTER(json_test_true);
    	AST_TEST_REGISTER(json_test_bool0);
    	AST_TEST_REGISTER(json_test_bool1);
    	AST_TEST_REGISTER(json_test_null);
    	AST_TEST_REGISTER(json_test_null_val);
    	AST_TEST_REGISTER(json_test_string);
    	AST_TEST_REGISTER(json_test_string_null);
    	AST_TEST_REGISTER(json_test_stringf);
    	AST_TEST_REGISTER(json_test_int);
    	AST_TEST_REGISTER(json_test_non_int);
    	AST_TEST_REGISTER(json_test_array_create);
    	AST_TEST_REGISTER(json_test_array_append);
    	AST_TEST_REGISTER(json_test_array_inset);
    	AST_TEST_REGISTER(json_test_array_set);
    	AST_TEST_REGISTER(json_test_array_remove);
    	AST_TEST_REGISTER(json_test_array_clear);
    	AST_TEST_REGISTER(json_test_array_extend);
    	AST_TEST_REGISTER(json_test_array_null);
    	AST_TEST_REGISTER(json_test_object_alloc);
    	AST_TEST_REGISTER(json_test_object_set);
    	AST_TEST_REGISTER(json_test_object_set_overwrite);
    	AST_TEST_REGISTER(json_test_object_get);
    	AST_TEST_REGISTER(json_test_object_del);
    	AST_TEST_REGISTER(json_test_object_clear);
    	AST_TEST_REGISTER(json_test_object_merge_all);
    	AST_TEST_REGISTER(json_test_object_merge_existing);
    	AST_TEST_REGISTER(json_test_object_merge_missing);
    	AST_TEST_REGISTER(json_test_object_null);
    	AST_TEST_REGISTER(json_test_object_iter);
    	AST_TEST_REGISTER(json_test_object_iter_null);
    	AST_TEST_REGISTER(json_test_dump_load_string);
    	AST_TEST_REGISTER(json_test_dump_load_str);
    	AST_TEST_REGISTER(json_test_dump_str_fail);
    	AST_TEST_REGISTER(json_test_load_buffer);
    	AST_TEST_REGISTER(json_test_dump_load_file);
    	AST_TEST_REGISTER(json_test_dump_load_new_file);
    	AST_TEST_REGISTER(json_test_dump_load_null);
    	AST_TEST_REGISTER(json_test_parse_errors);
    	AST_TEST_REGISTER(json_test_pack);
    
    	AST_TEST_REGISTER(json_test_pack_ownership);
    
    David M. Lee's avatar
    David M. Lee committed
    	AST_TEST_REGISTER(json_test_pack_errors);
    	AST_TEST_REGISTER(json_test_copy);
    	AST_TEST_REGISTER(json_test_deep_copy);
    	AST_TEST_REGISTER(json_test_copy_null);
    	AST_TEST_REGISTER(json_test_circular_object);
    	AST_TEST_REGISTER(json_test_circular_array);
    	AST_TEST_REGISTER(json_test_clever_circle);
    
    	AST_TEST_REGISTER(json_test_name_number);
    	AST_TEST_REGISTER(json_test_timeval);
    	AST_TEST_REGISTER(json_test_cep);
    
    
    	ast_test_register_init(CATEGORY, json_test_init);
    	ast_test_register_cleanup(CATEGORY, json_test_cleanup);
    
    
    David M. Lee's avatar
    David M. Lee committed
    	return AST_MODULE_LOAD_SUCCESS;
    }
    
    
    AST_MODULE_INFO(ASTERISK_GPL_KEY, 0, "JSON testing",