static char *test_parser_fixed_scalars(void *context) { int idx = 0; static char error[1024]; while (fs_vectors[idx].data) { qd_field_iterator_t *field = qd_field_iterator_binary(fs_vectors[idx].data, fs_vectors[idx].length); qd_parsed_field_t *parsed = qd_parse(field); if (!qd_parse_ok(parsed)) return "Unexpected Parse Error"; if (qd_parse_tag(parsed) != fs_vectors[idx].expected_tag) { sprintf(error, "(%d) Tag: Expected %02x, Got %02x", idx, fs_vectors[idx].expected_tag, qd_parse_tag(parsed)); return error; } if (fs_vectors[idx].check_uint && qd_parse_as_uint(parsed) != fs_vectors[idx].expected_ulong) { sprintf(error, "(%d) UINT: Expected %"PRIx64", Got %"PRIx32, idx, fs_vectors[idx].expected_ulong, qd_parse_as_uint(parsed)); return error; } if (fs_vectors[idx].check_ulong && qd_parse_as_ulong(parsed) != fs_vectors[idx].expected_ulong) { sprintf(error, "(%d) ULONG: Expected %"PRIx64", Got %"PRIx64, idx, fs_vectors[idx].expected_ulong, qd_parse_as_ulong(parsed)); return error; } if (fs_vectors[idx].check_int && qd_parse_as_int(parsed) != fs_vectors[idx].expected_long) { sprintf(error, "(%d) INT: Expected %"PRIx64", Got %"PRIx32, idx, fs_vectors[idx].expected_long, qd_parse_as_int(parsed)); return error; } if (fs_vectors[idx].check_long && qd_parse_as_long(parsed) != fs_vectors[idx].expected_long) { sprintf(error, "(%d) LONG: Expected %"PRIx64", Got %"PRIx64, idx, fs_vectors[idx].expected_long, qd_parse_as_long(parsed)); return error; } idx++; qd_field_iterator_free(field); qd_parse_free(parsed); } return 0; }
static char *test_parser_fixed_scalars(void *context) { int idx = 0; qd_iterator_t *field = NULL; qd_parsed_field_t *parsed = NULL; static char error[1024]; error[0] = 0; while (fs_vectors[idx].data) { field = qd_iterator_binary(fs_vectors[idx].data, fs_vectors[idx].length, ITER_VIEW_ALL); parsed = qd_parse(field); qd_iterator_t *typed_iter = qd_parse_typed(parsed); int length = qd_iterator_length(typed_iter); if (length != fs_vectors[idx].length) { strcpy(error, "Length of typed iterator does not match actual length"); break; } if (!qd_parse_ok(parsed)) { strcpy(error, "Unexpected Parse Error"); break; } if (qd_parse_tag(parsed) != fs_vectors[idx].expected_tag) { sprintf(error, "(%d) Tag: Expected %02x, Got %02x", idx, fs_vectors[idx].expected_tag, qd_parse_tag(parsed)); break; } if (fs_vectors[idx].check_uint && qd_parse_as_uint(parsed) != fs_vectors[idx].expected_ulong) { sprintf(error, "(%d) UINT: Expected %"PRIx64", Got %"PRIx32, idx, fs_vectors[idx].expected_ulong, qd_parse_as_uint(parsed)); break; } if (fs_vectors[idx].check_ulong && qd_parse_as_ulong(parsed) != fs_vectors[idx].expected_ulong) { sprintf(error, "(%d) ULONG: Expected %"PRIx64", Got %"PRIx64, idx, fs_vectors[idx].expected_ulong, qd_parse_as_ulong(parsed)); break; } if (fs_vectors[idx].check_int && qd_parse_as_int(parsed) != fs_vectors[idx].expected_long) { sprintf(error, "(%d) INT: Expected %"PRIx64", Got %"PRIx32, idx, fs_vectors[idx].expected_long, qd_parse_as_int(parsed)); break; } if (fs_vectors[idx].check_long && qd_parse_as_long(parsed) != fs_vectors[idx].expected_long) { sprintf(error, "(%d) LONG: Expected %"PRIx64", Got %"PRIx64, idx, fs_vectors[idx].expected_long, qd_parse_as_long(parsed)); break; } idx++; qd_iterator_free(field); field = 0; qd_parse_free(parsed); parsed = 0; } qd_iterator_free(field); qd_parse_free(parsed); return *error ? error : 0; }
static char *test_map(void *context) { static char error[1000]; const char *data = "\xd1\x00\x00\x00\x2d\x00\x00\x00\x06" // map32, 6 items "\xa3\x05\x66irst\xa1\x0evalue_of_first" // (23) "first":"value_of_first" "\xa3\x06second\x52\x20" // (10) "second":32 "\xa3\x05third\x41"; // (8) "third":true int data_len = 50; qd_iterator_t *data_iter = qd_iterator_binary(data, data_len, ITER_VIEW_ALL); qd_parsed_field_t *field = qd_parse(data_iter); if (!qd_parse_ok(field)) { snprintf(error, 1000, "Parse failed: %s", qd_parse_error(field)); qd_iterator_free(data_iter); qd_parse_free(field); return error; } if (!qd_parse_is_map(field)) { qd_iterator_free(data_iter); qd_parse_free(field); return "Expected field to be a map"; } uint32_t count = qd_parse_sub_count(field); if (count != 3) { snprintf(error, 1000, "Expected sub-count==3, got %"PRIu32, count); qd_iterator_free(data_iter); qd_parse_free(field); return error; } qd_parsed_field_t *key_field = qd_parse_sub_key(field, 0); qd_iterator_t *key_iter = qd_parse_raw(key_field); qd_iterator_t *typed_iter = qd_parse_typed(key_field); if (!qd_iterator_equal(key_iter, (unsigned char*) "first")) { unsigned char *result = qd_iterator_copy(key_iter); snprintf(error, 1000, "First key: expected 'first', got '%s'", result); free (result); return error; } if (!qd_iterator_equal(typed_iter, (unsigned char*) "\xa3\x05\x66irst")) return "Incorrect typed iterator on first-key"; qd_parsed_field_t *val_field = qd_parse_sub_value(field, 0); qd_iterator_t *val_iter = qd_parse_raw(val_field); typed_iter = qd_parse_typed(val_field); if (!qd_iterator_equal(val_iter, (unsigned char*) "value_of_first")) { unsigned char *result = qd_iterator_copy(val_iter); snprintf(error, 1000, "First value: expected 'value_of_first', got '%s'", result); free (result); return error; } if (!qd_iterator_equal(typed_iter, (unsigned char*) "\xa1\x0evalue_of_first")) return "Incorrect typed iterator on first-key"; key_field = qd_parse_sub_key(field, 1); key_iter = qd_parse_raw(key_field); if (!qd_iterator_equal(key_iter, (unsigned char*) "second")) { unsigned char *result = qd_iterator_copy(key_iter); snprintf(error, 1000, "Second key: expected 'second', got '%s'", result); free (result); return error; } val_field = qd_parse_sub_value(field, 1); if (qd_parse_as_uint(val_field) != 32) { snprintf(error, 1000, "Second value: expected 32, got %"PRIu32, qd_parse_as_uint(val_field)); return error; } key_field = qd_parse_sub_key(field, 2); key_iter = qd_parse_raw(key_field); if (!qd_iterator_equal(key_iter, (unsigned char*) "third")) { unsigned char *result = qd_iterator_copy(key_iter); snprintf(error, 1000, "Third key: expected 'third', got '%s'", result); free (result); return error; } val_field = qd_parse_sub_value(field, 2); if (!qd_parse_as_bool(val_field)) { snprintf(error, 1000, "Third value: expected true"); return error; } qd_iterator_free(data_iter); qd_parse_free(field); return 0; }
static char *test_integer_conversion(void *context) { const struct fs_vector_t { const char *data; int length; uint8_t parse_as; bool expect_fail; int64_t expected_int; uint64_t expected_uint; } fs_vectors[] = { // can successfully convert 64 bit values that are valid in the 32bit range {"\x80\x00\x00\x00\x00\xff\xff\xff\xff", 9, QD_AMQP_UINT, false, 0, UINT32_MAX}, {"\x80\x00\x00\x00\x00\x00\x00\x00\x00", 9, QD_AMQP_UINT, false, 0, 0}, {"\x80\x00\x00\x00\x00\x00\x00\x00\x01", 9, QD_AMQP_UINT, false, 0, 1}, {"\x81\x00\x00\x00\x00\x7f\xff\xff\xff", 9, QD_AMQP_INT, false, INT32_MAX, 0}, {"\x81\xFF\xFF\xFF\xFF\x80\x00\x00\x00", 9, QD_AMQP_INT, false, INT32_MIN, 0}, {"\x81\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9, QD_AMQP_INT, false, -1, 0}, // signed/unsigned conversions {"\x70\x7F\xFF\xFF\xFF", 5, QD_AMQP_INT, false, INT32_MAX, 0}, {"\x71\x7F\xFF\xFF\xFF", 5, QD_AMQP_UINT, false, 0, INT32_MAX}, {"\x80\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9, QD_AMQP_LONG, false, INT64_MAX, 0}, {"\x81\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 9, QD_AMQP_ULONG, false,0, INT64_MAX}, {"\x50\x7F", 2, QD_AMQP_INT, false, INT8_MAX, 0}, {"\x60\x7F\xFF", 3, QD_AMQP_INT, false, INT16_MAX, 0}, {"\x53\x7F", 2, QD_AMQP_INT, false, INT8_MAX, 0}, {"\x55\x7F", 2, QD_AMQP_UINT, false, 0, INT8_MAX}, {"\x51\x7F", 2, QD_AMQP_UINT, false, 0, INT8_MAX}, {"\x61\x7F\xFF", 3, QD_AMQP_UINT, false, 0, INT16_MAX}, // strings {"\xa1\x02 1", 4, QD_AMQP_UINT, false, 0, 1}, {"\xa1\x02-1", 4, QD_AMQP_INT, false, -1, 0}, {"\xa1\x14" "18446744073709551615", 22, QD_AMQP_ULONG,false, 0, UINT64_MAX}, {"\xa1\x14" "-9223372036854775808", 22, QD_AMQP_LONG, false, INT64_MIN, 0}, {"\xa1\x13" "9223372036854775807", 21, QD_AMQP_LONG, false, INT64_MAX, 0}, {"\xa3\x13" "9223372036854775807", 21, QD_AMQP_LONG, false, INT64_MAX, 0}, // cannot convert 64 bit values that are outside the 32bit range as int32 {"\x80\x00\x00\x00\x01\x00\x00\x00\x00", 9, QD_AMQP_UINT, true, 0, 0}, {"\x81\x00\x00\x00\x00\x80\x00\x00\x00", 9, QD_AMQP_INT, true, 0, 0}, {"\x81\xFF\xFF\xFF\xFF\x7F\xFF\xFF\xFF", 9, QD_AMQP_INT, true, 0, 0}, // bad signed/unsigned conversions {"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 9, QD_AMQP_LONG, true, 0, 0}, {"\x81\x80\x00\x00\x00\x00\x00\x00\x00", 9, QD_AMQP_ULONG, true, 0, 0}, {"\x70\x80\x00\x00\x00", 5, QD_AMQP_LONG, true, 0, 0}, {"\x71\x80\x00\x00\x00", 5, QD_AMQP_ULONG, true, 0, 0}, {"\x55\x80", 2, QD_AMQP_UINT, true, 0, 0}, {"\x51\x80", 2, QD_AMQP_UINT, true, 0, 0}, {"\x54\x80", 2, QD_AMQP_UINT, true, 0, 0}, {"\x61\x80\x00", 3, QD_AMQP_UINT, true, 0, 0}, {"\x53\x80", 2, QD_AMQP_INT, true, 0, 0}, {"\x52\x80", 2, QD_AMQP_INT, true, 0, 0}, {"\x50\x80", 2, QD_AMQP_LONG, true, 0, 0}, {"\x60\x80", 2, QD_AMQP_LONG, true, 0, 0}, {NULL}, }; char *error = NULL; for (int i = 0; fs_vectors[i].data && !error; ++i) { qd_iterator_t *data_iter = qd_iterator_binary(fs_vectors[i].data, fs_vectors[i].length, ITER_VIEW_ALL); qd_parsed_field_t *field = qd_parse(data_iter); if (!qd_parse_ok(field)) { error = "unexpected parse error"; qd_iterator_free(data_iter); qd_parse_free(field); break; } bool equal = false; switch (fs_vectors[i].parse_as) { case QD_AMQP_UINT: { uint32_t tmp = qd_parse_as_uint(field); equal = (tmp == fs_vectors[i].expected_uint); break; } case QD_AMQP_ULONG: { uint64_t tmp = qd_parse_as_ulong(field); equal = (tmp == fs_vectors[i].expected_uint); break; } case QD_AMQP_INT: { int32_t tmp = qd_parse_as_int(field); equal = (tmp == fs_vectors[i].expected_int); break; } case QD_AMQP_LONG: { int64_t tmp = qd_parse_as_long(field); equal = (tmp == fs_vectors[i].expected_int); break; } } if (!qd_parse_ok(field)) { if (!fs_vectors[i].expect_fail) { error = "unexpected conversion/parse error"; } } else if (fs_vectors[i].expect_fail) { error = "Conversion did not fail as expected"; } else if (!equal) { error = "unexpected converted value"; } qd_iterator_free(data_iter); qd_parse_free(field); } return error; }
PyObject *qd_field_to_py(qd_parsed_field_t *field) { qd_python_check_lock(); PyObject *result = 0; uint8_t tag = qd_parse_tag(field); switch (tag) { case QD_AMQP_NULL: Py_INCREF(Py_None); result = Py_None; break; case QD_AMQP_BOOLEAN: case QD_AMQP_TRUE: case QD_AMQP_FALSE: result = qd_parse_as_uint(field) ? Py_True : Py_False; break; case QD_AMQP_UBYTE: case QD_AMQP_USHORT: case QD_AMQP_UINT: case QD_AMQP_SMALLUINT: case QD_AMQP_UINT0: result = PyInt_FromLong((long) qd_parse_as_uint(field)); break; case QD_AMQP_ULONG: case QD_AMQP_SMALLULONG: case QD_AMQP_ULONG0: case QD_AMQP_TIMESTAMP: result = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) qd_parse_as_ulong(field)); break; case QD_AMQP_BYTE: case QD_AMQP_SHORT: case QD_AMQP_INT: case QD_AMQP_SMALLINT: result = PyInt_FromLong((long) qd_parse_as_int(field)); break; case QD_AMQP_LONG: case QD_AMQP_SMALLLONG: result = PyLong_FromLongLong((PY_LONG_LONG)qd_parse_as_long(field)); break; case QD_AMQP_FLOAT: case QD_AMQP_DOUBLE: case QD_AMQP_DECIMAL32: case QD_AMQP_DECIMAL64: case QD_AMQP_DECIMAL128: case QD_AMQP_UTF32: case QD_AMQP_UUID: break; case QD_AMQP_VBIN8: case QD_AMQP_VBIN32: case QD_AMQP_STR8_UTF8: case QD_AMQP_STR32_UTF8: case QD_AMQP_SYM8: case QD_AMQP_SYM32: result = parsed_to_py_string(field); break; case QD_AMQP_LIST0: case QD_AMQP_LIST8: case QD_AMQP_LIST32: { uint32_t count = qd_parse_sub_count(field); result = PyList_New(count); for (uint32_t idx = 0; idx < count; idx++) { qd_parsed_field_t *sub = qd_parse_sub_value(field, idx); PyObject *pysub = qd_field_to_py(sub); if (pysub == 0) return 0; PyList_SetItem(result, idx, pysub); } break; } case QD_AMQP_MAP8: case QD_AMQP_MAP32: { uint32_t count = qd_parse_sub_count(field); result = PyDict_New(); for (uint32_t idx = 0; idx < count; idx++) { qd_parsed_field_t *key = qd_parse_sub_key(field, idx); qd_parsed_field_t *val = qd_parse_sub_value(field, idx); PyObject *pykey = parsed_to_py_string(key); PyObject *pyval = qd_field_to_py(val); if (pyval == 0) return 0; PyDict_SetItem(result, pykey, pyval); Py_DECREF(pykey); Py_DECREF(pyval); } break; } case QD_AMQP_ARRAY8: case QD_AMQP_ARRAY32: break; } if (!result) Py_RETURN_NONE; return result; }