You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by hu...@apache.org on 2015/11/02 07:13:58 UTC
[2/3] incubator-hawq git commit: HAWQ-86. Fix and re-enable unit test
for pxf and external storage
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test/pxffilters_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test/pxffilters_test.c b/src/backend/access/external/test/pxffilters_test.c
new file mode 100644
index 0000000..8f96550
--- /dev/null
+++ b/src/backend/access/external/test/pxffilters_test.c
@@ -0,0 +1,556 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include "cmockery.h"
+
+#include "c.h"
+#include "../pxffilters.c"
+
+void
+test__supported_filter_type(void **state)
+{
+ Oid oids[] =
+ {
+ INT2OID,
+ INT4OID,
+ INT8OID,
+ FLOAT4OID,
+ FLOAT8OID,
+ NUMERICOID,
+ TEXTOID,
+ VARCHAROID,
+ BPCHAROID,
+ CHAROID,
+ BYTEAOID,
+ BOOLOID,
+ CIRCLEOID /* unsupported type */
+ };
+
+ int array_size = sizeof(oids) / sizeof(oids[0]);
+ bool result = false;
+ int i = 0;
+
+ /* supported types */
+ for (; i < array_size-1; ++i)
+ {
+ result = supported_filter_type(oids[i]);
+ assert_true(result);
+ }
+ /* unsupported type */
+ result = supported_filter_type(oids[i]);
+ assert_false(result);
+
+ /* go over pxf_supported_types array */
+ int nargs = sizeof(pxf_supported_types) / sizeof(Oid);
+ assert_int_equal(nargs, 12);
+ for (i = 0; i < nargs; ++i)
+ {
+ assert_true(supported_filter_type(pxf_supported_types[i]));
+ }
+
+}
+
+/*
+ * const_value must be palloc'ed, it will be freed by const_to_str
+ */
+void
+mock__const_to_str(Oid const_type, char* const_value)
+{
+ expect_value(getTypeOutputInfo, type, const_type);
+ expect_any(getTypeOutputInfo, typOutput);
+ expect_any(getTypeOutputInfo, typIsVarlena);
+ will_return(getTypeOutputInfo, NULL);
+
+ expect_any(OidOutputFunctionCall, functionId);
+ expect_any(OidOutputFunctionCall, val);
+ will_return(OidOutputFunctionCall, const_value);
+}
+
+void
+verify__const_to_str(bool is_null, char* const_value, Oid const_type, char* expected)
+{
+ StringInfo result = makeStringInfo();
+ char* value = NULL;
+ Const* input = (Const*) palloc0(sizeof(Const));
+ input->constisnull = is_null;
+ input->consttype = const_type;
+
+ /* need to prepare inner functions */
+ if (!is_null)
+ {
+ value = strdup(const_value); /* will be free'd by const_to_str */
+
+ mock__const_to_str(const_type, value);
+ }
+
+ /* no expected value means it's a negative test */
+ if (expected)
+ {
+ run__const_to_str(input, result, expected);
+ }
+ else
+ {
+ run__const_to_str__negative(input, result, value);
+ pfree(value); /* value was not freed by const_to_str b/c of failure */
+ }
+
+ pfree(result->data);
+ pfree(result);
+ pfree(input);
+}
+
+void run__const_to_str(Const* input, StringInfo result, char* expected)
+{
+ const_to_str(input, result);
+ assert_string_equal(result->data, expected);
+}
+
+void run__const_to_str__negative(Const* input, StringInfo result, char* value)
+{
+
+ StringInfo err_msg = makeStringInfo();
+ appendStringInfo(err_msg,
+ "internal error in pxffilters.c:const_to_str. "
+ "Using unsupported data type (%d) (value %s)", input->consttype, value);
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ const_to_str(input, result);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /* Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_INTERNAL_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, err_msg->data);
+
+ pfree(err_msg->data);
+ pfree(err_msg);
+
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+
+void
+test__const_to_str__null(void **state)
+{
+ verify__const_to_str(true, NULL, 1, "\"NULL\"");
+}
+
+void
+test__const_to_str__int(void **state)
+{
+ verify__const_to_str(false, "1234", INT2OID, "1234");
+ verify__const_to_str(false, "1234", INT4OID, "1234");
+ verify__const_to_str(false, "1234", INT8OID, "1234");
+ verify__const_to_str(false, "1.234", FLOAT4OID, "1.234");
+ verify__const_to_str(false, "1.234", FLOAT8OID, "1.234");
+ verify__const_to_str(false, "1234", NUMERICOID, "1234");
+}
+
+void
+test__const_to_str__text(void **state)
+{
+ verify__const_to_str(false, "that", TEXTOID, "\\\"that\\\"");
+ verify__const_to_str(false, "joke", VARCHAROID, "\\\"joke\\\"");
+ verify__const_to_str(false, "isn't", BPCHAROID, "\\\"isn't\\\"");
+ verify__const_to_str(false, "funny", CHAROID, "\\\"funny\\\"");
+ verify__const_to_str(false, "anymore", BYTEAOID, "\\\"anymore\\\"");
+}
+
+void
+test__const_to_str__boolean(void **state)
+{
+ verify__const_to_str(false, "t", BOOLOID, "\"true\"");
+ verify__const_to_str(false, "f", BOOLOID, "\"false\"");
+}
+
+void
+test__const_to_str__NegativeCircle(void **state)
+{
+ verify__const_to_str(false, "<3,3,9>", CIRCLEOID, NULL);
+}
+
+void
+test__opexpr_to_pxffilter__null(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ OpExpr *expr = (OpExpr*) palloc0(sizeof(OpExpr));
+
+ assert_false(opexpr_to_pxffilter(NULL, NULL));
+ assert_false(opexpr_to_pxffilter(NULL, filter));
+ assert_false(opexpr_to_pxffilter(expr, NULL));
+
+ expr->args = NIL;
+ assert_false(opexpr_to_pxffilter(expr, filter));
+
+ pfree(filter);
+ pfree(expr);
+}
+
+void
+test__opexpr_to_pxffilter__unary_expr(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ OpExpr *expr = (OpExpr*) palloc0(sizeof(OpExpr));
+ Var *arg = (Var*) palloc0(sizeof(Var));
+ arg->xpr.type = T_Var;
+
+ assert_false(opexpr_to_pxffilter(NULL, NULL));
+ assert_false(opexpr_to_pxffilter(NULL, filter));
+ assert_false(opexpr_to_pxffilter(expr, NULL));
+
+ expr->args = NIL;
+ expr->args = lappend(expr->args, arg);
+ assert_false(opexpr_to_pxffilter(expr, filter));
+
+ pfree(arg);
+ pfree(filter);
+ pfree(expr);
+}
+
+void
+compare_filters(PxfFilterDesc* result, PxfFilterDesc* expected)
+{
+ assert_int_equal(result->l.opcode, expected->l.opcode);
+ assert_int_equal(result->l.attnum, expected->l.attnum);
+ if (expected->l.conststr)
+ assert_string_equal(result->l.conststr->data, expected->l.conststr->data);
+ else
+ assert_true(result->l.conststr == NULL);
+
+ assert_true(result->r.opcode == expected->r.opcode);
+ assert_int_equal(result->r.attnum, expected->r.attnum);
+ if (expected->r.conststr)
+ assert_string_equal(result->r.conststr->data, expected->r.conststr->data);
+ else
+ assert_true(result->r.conststr == NULL);
+
+ assert_int_equal(result->op, expected->op);
+}
+
+PxfFilterDesc* build_filter(char lopcode, int lattnum, char* lconststr,
+ char ropcode, int rattnum, char* rconststr,
+ PxfOperatorCode op)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+
+ filter->l.opcode = lopcode;
+ filter->l.attnum = lattnum;
+ if (lconststr)
+ {
+ filter->l.conststr = makeStringInfo();
+ appendStringInfoString(filter->l.conststr, lconststr);
+ }
+
+ filter->r.opcode = ropcode;
+ filter->r.attnum = rattnum;
+ if (rconststr)
+ {
+ filter->r.conststr = makeStringInfo();
+ appendStringInfoString(filter->r.conststr, rconststr);
+ }
+
+ filter->op = op;
+
+ return filter;
+}
+
+Var* build_var(Oid oid, int attno) {
+ Var *arg_var = (Var*) palloc0(sizeof(Var));
+ arg_var->xpr.type = T_Var;
+ arg_var->vartype = oid;
+ arg_var->varattno = attno;
+ return arg_var;
+}
+
+Const* build_const(Oid oid, char* value)
+{
+ Const* arg_const = (Const*) palloc0(sizeof(Const));
+ arg_const->xpr.type = T_Const;
+ arg_const->constisnull = (value == NULL);
+ arg_const->consttype = oid;
+ if (value != NULL)
+ {
+ mock__const_to_str(oid, value);
+ }
+
+ return arg_const;
+}
+
+OpExpr* build_op_expr(void* left, void* right, int op)
+{
+ OpExpr *expr = (OpExpr*) palloc0(sizeof(OpExpr));
+ expr->args = NIL;
+ expr->args = lappend(expr->args, left);
+ expr->args = lappend(expr->args, right);
+
+ expr->opno = op;
+ expr->xpr.type = T_OpExpr;
+ return expr;
+}
+
+void run__opexpr_to_pxffilter__positive(Oid dbop, PxfOperatorCode expectedPxfOp)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ Var *arg_var = build_var(INT2OID, 1);
+ char* const_value = strdup("1984"); /* will be free'd by const_to_str */
+ Const* arg_const = build_const(INT2OID, const_value);
+
+ OpExpr *expr = build_op_expr(arg_var, arg_const, dbop);
+ PxfFilterDesc* expected = build_filter(
+ PXF_ATTR_CODE, 1, NULL,
+ PXF_CONST_CODE, 0, "1984",
+ expectedPxfOp);
+
+ /* run test */
+ assert_true(opexpr_to_pxffilter(expr, filter));
+
+ compare_filters(filter, expected);
+
+ pxf_free_filter(expected);
+ pxf_free_filter(filter);
+
+ list_free_deep(expr->args); /* free all args */
+ pfree(expr);
+}
+
+void
+test__opexpr_to_pxffilter__intGT(void **state)
+{
+ run__opexpr_to_pxffilter__positive(520 /* int2gt */, PXFOP_GT);
+}
+
+void
+test__opexpr_to_pxffilter__allSupportedTypes(void **state)
+{
+ int nargs = sizeof(pxf_supported_opr) / sizeof(dbop_pxfop_map);
+ PxfOperatorCode pxfop = 0;
+ Oid dbop = InvalidOid;
+
+ for (int i = 0; i < nargs; ++i)
+ {
+ dbop = pxf_supported_opr[i].dbop;
+ pxfop = pxf_supported_opr[i].pxfop;
+ run__opexpr_to_pxffilter__positive(dbop, pxfop);
+ }
+}
+
+/* NOTE: this test is not a use case - when the query includes
+ * 'is null' or 'is not null' the qualifier code is T_NullTest and not T_OpExpr */
+void
+test__opexpr_to_pxffilter__attributeIsNull(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ Var *arg_var = build_var(INT2OID, 1);
+ Const* arg_const = build_const(INT2OID, NULL);
+ OpExpr *expr = build_op_expr(arg_var, arg_const, 94 /* int2eq */);
+
+ PxfFilterDesc* expected = build_filter(
+ PXF_ATTR_CODE, 1, NULL,
+ PXF_CONST_CODE, 0, "\"NULL\"",
+ PXFOP_EQ);
+
+ /* run test */
+ assert_true(opexpr_to_pxffilter(expr, filter));
+ compare_filters(filter, expected);
+
+ pxf_free_filter(filter);
+ pxf_free_filter(expected);
+
+ list_free_deep(expr->args); /* free all args */
+ pfree(expr);
+}
+
+/*
+ * Test for a query with different types.
+ * Types pairing are not checked, it is covered by the
+ * supported operations which are type specific.
+ */
+void
+test__opexpr_to_pxffilter__differentTypes(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ Var *arg_var = build_var(INT2OID, 3);
+ char* const_value = strdup("13"); /* will be free'd by const_to_str */
+ Const *arg_const = build_const(INT8OID, const_value);
+ OpExpr *expr = build_op_expr(arg_const, arg_var, 1864 /* int28lt */);
+
+
+ /* run test */
+ assert_true(opexpr_to_pxffilter(expr, filter));
+ PxfFilterDesc *expected = build_filter(
+ PXF_CONST_CODE, 0, "13",
+ PXF_ATTR_CODE, 3, NULL,
+ PXFOP_LT);
+ compare_filters(filter, expected);
+
+ pxf_free_filter(filter);
+ list_free_deep(expr->args); /* free all args */
+ pfree(expr);
+}
+
+void
+test__opexpr_to_pxffilter__unsupportedTypeCircle(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ Var *arg_var = build_var(CIRCLEOID, 8);
+ Const *arg_const = build_const(CIRCLEOID, NULL);
+ OpExpr *expr = build_op_expr(arg_const, arg_var, 0 /* whatever */);
+
+ /* run test */
+ assert_false(opexpr_to_pxffilter(expr, filter));
+
+ pxf_free_filter(filter);
+
+ list_free_deep(expr->args); /* free all args */
+ pfree(expr);
+}
+
+void
+test__opexpr_to_pxffilter__twoVars(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ Var *arg_var_left = build_var(INT4OID, 8);
+ Var *arg_var_right = build_var(INT4OID, 9);
+ OpExpr *expr = build_op_expr(arg_var_left, arg_var_right, 0 /* whatever */);
+
+ /* run test */
+ assert_false(opexpr_to_pxffilter(expr, filter));
+
+ pxf_free_filter(filter);
+
+ list_free_deep(expr->args); /* free all args */
+ pfree(expr);
+}
+
+void
+test__opexpr_to_pxffilter__unsupportedOpNot(void **state)
+{
+ PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
+ Var *arg_var = build_var(INT2OID, 3);
+ char* const_value = strdup("not"); /* will be free'd by const_to_str */
+ Const *arg_const = build_const(INT2OID, const_value);
+ OpExpr *expr = build_op_expr(arg_const, arg_var, 1877 /* int2not */);
+
+ /* run test */
+ assert_false(opexpr_to_pxffilter(expr, filter));
+
+ pxf_free_filter(filter);
+
+ list_free_deep(expr->args); /* free all args */
+ pfree(expr);
+}
+
+void
+test__pxf_serialize_filter_list__oneFilter(void **state)
+{
+ List* filter_list = NIL;
+
+ PxfFilterDesc* filter = build_filter(
+ PXF_ATTR_CODE, 1, NULL,
+ PXF_CONST_CODE, 0, "1984",
+ PXFOP_GT);
+ filter_list = lappend(filter_list, filter);
+
+ char* result = pxf_serialize_filter_list(filter_list);
+ assert_string_equal(result, "a0c1984o2");
+
+ pxf_free_filter_list(filter_list);
+ filter_list = NIL;
+ pfree(result);
+
+ filter = build_filter(
+ PXF_ATTR_CODE, 8, NULL,
+ PXF_CONST_CODE, 0, "\"George Orwell\"",
+ PXFOP_EQ);
+ filter_list = lappend(filter_list, filter);
+
+ result = pxf_serialize_filter_list(filter_list);
+ assert_string_equal(result, "a7c\"George Orwell\"o5");
+
+ pxf_free_filter_list(filter_list);
+ pfree(result);
+}
+
+void
+test__pxf_serialize_filter_list__manyFilters(void **state)
+{
+ char* result = NULL;
+ List* filter_list = NIL;
+
+ PxfFilterDesc* filter1 = build_filter(
+ PXF_ATTR_CODE, 2, NULL,
+ PXF_CONST_CODE, 0, "1983",
+ PXFOP_GT);
+ PxfFilterDesc* filter2 = build_filter(
+ PXF_ATTR_CODE, 3, NULL,
+ PXF_CONST_CODE, 0, "1985",
+ PXFOP_LT);
+ PxfFilterDesc* filter3 = build_filter(
+ PXF_ATTR_CODE, 4, NULL,
+ PXF_CONST_CODE, 0, "\"George Orwell\"",
+ PXFOP_EQ);
+ PxfFilterDesc* filter4 = build_filter(
+ PXF_ATTR_CODE, 5, NULL,
+ PXF_CONST_CODE, 0, "\"Winston\"",
+ PXFOP_GE);
+
+ filter_list = lappend(filter_list, filter1);
+ filter_list = lappend(filter_list, filter2);
+
+ result = pxf_serialize_filter_list(filter_list);
+ assert_string_equal(result, "a1c1983o2a2c1985o1o7");
+ pfree(result);
+
+ filter_list = lappend(filter_list, filter3);
+
+ result = pxf_serialize_filter_list(filter_list);
+ assert_string_equal(result, "a1c1983o2a2c1985o1o7a3c\"George Orwell\"o5o7");
+ pfree(result);
+
+ filter_list = lappend(filter_list, filter4);
+
+ result = pxf_serialize_filter_list(filter_list);
+ assert_string_equal(result, "a1c1983o2a2c1985o1o7a3c\"George Orwell\"o5o7a4c\"Winston\"o4o7");
+ pfree(result);
+
+ pxf_free_filter_list(filter_list);
+ filter_list = NIL;
+}
+
+int
+main(int argc, char* argv[])
+{
+ cmockery_parse_arguments(argc, argv);
+
+ const UnitTest tests[] = {
+ unit_test(test__supported_filter_type),
+ unit_test(test__const_to_str__null),
+ unit_test(test__const_to_str__int),
+ unit_test(test__const_to_str__text),
+ unit_test(test__const_to_str__boolean),
+ unit_test(test__const_to_str__NegativeCircle),
+ unit_test(test__opexpr_to_pxffilter__null),
+ unit_test(test__opexpr_to_pxffilter__unary_expr),
+ unit_test(test__opexpr_to_pxffilter__intGT),
+ unit_test(test__opexpr_to_pxffilter__allSupportedTypes),
+ unit_test(test__opexpr_to_pxffilter__attributeIsNull),
+ unit_test(test__opexpr_to_pxffilter__differentTypes),
+ unit_test(test__opexpr_to_pxffilter__unsupportedTypeCircle),
+ unit_test(test__opexpr_to_pxffilter__twoVars),
+ unit_test(test__opexpr_to_pxffilter__unsupportedOpNot),
+ unit_test(test__pxf_serialize_filter_list__oneFilter),
+ unit_test(test__pxf_serialize_filter_list__manyFilters)
+ };
+ return run_tests(tests);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test/pxfheaders_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test/pxfheaders_test.c b/src/backend/access/external/test/pxfheaders_test.c
new file mode 100644
index 0000000..159d684
--- /dev/null
+++ b/src/backend/access/external/test/pxfheaders_test.c
@@ -0,0 +1,223 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include "cmockery.h"
+
+#include "c.h"
+#include "../pxfheaders.c"
+
+static GPHDUri *gphd_uri = NULL;
+static PxfInputData *input_data = NULL;
+static extvar_t *mock_extvar = NULL;
+
+static char *old_pxf_remote_service_login = NULL;
+static char *old_pxf_remote_service_secret = NULL;
+
+void
+test__build_http_header__remote_login_is_null(void **state)
+{
+ expect_external_vars();
+
+ expect_churl_headers("X-GP-SEGMENT-ID", mock_extvar->GP_SEGMENT_ID);
+ expect_churl_headers("X-GP-SEGMENT-COUNT", mock_extvar->GP_SEGMENT_COUNT);
+ expect_churl_headers("X-GP-XID", mock_extvar->GP_XID);
+ expect_churl_headers_alignment();
+ expect_churl_headers("X-GP-URL-HOST", gphd_uri->host);
+ expect_churl_headers("X-GP-URL-PORT", gphd_uri->port);
+ expect_churl_headers("X-GP-DATA-DIR", gphd_uri->data);
+ expect_churl_headers("X-GP-URI", gphd_uri->uri);
+ expect_churl_headers("X-GP-HAS-FILTER", "0");
+
+ build_http_header(input_data);
+}
+
+void
+test__build_http_header__remote_login_is_not_null(void **state)
+{
+ expect_external_vars();
+
+ expect_churl_headers("X-GP-SEGMENT-ID", mock_extvar->GP_SEGMENT_ID);
+ expect_churl_headers("X-GP-SEGMENT-COUNT", mock_extvar->GP_SEGMENT_COUNT);
+ expect_churl_headers("X-GP-XID", mock_extvar->GP_XID);
+ expect_churl_headers_alignment();
+ expect_churl_headers("X-GP-URL-HOST", gphd_uri->host);
+ expect_churl_headers("X-GP-URL-PORT", gphd_uri->port);
+ expect_churl_headers("X-GP-DATA-DIR", gphd_uri->data);
+ expect_churl_headers("X-GP-URI", gphd_uri->uri);
+ expect_churl_headers("X-GP-HAS-FILTER", "0");
+
+ pxf_remote_service_login = "not a valid login";
+ expect_churl_headers("X-GP-REMOTE-USER", pxf_remote_service_login);
+
+ build_http_header(input_data);
+}
+
+void
+test__build_http_header__remote_secret_is_not_null(void **state)
+{
+ expect_external_vars();
+
+ expect_churl_headers("X-GP-SEGMENT-ID", mock_extvar->GP_SEGMENT_ID);
+ expect_churl_headers("X-GP-SEGMENT-COUNT", mock_extvar->GP_SEGMENT_COUNT);
+ expect_churl_headers("X-GP-XID", mock_extvar->GP_XID);
+ expect_churl_headers_alignment();
+ expect_churl_headers("X-GP-URL-HOST", gphd_uri->host);
+ expect_churl_headers("X-GP-URL-PORT", gphd_uri->port);
+ expect_churl_headers("X-GP-DATA-DIR", gphd_uri->data);
+ expect_churl_headers("X-GP-URI", gphd_uri->uri);
+ expect_churl_headers("X-GP-HAS-FILTER", "0");
+
+ pxf_remote_service_secret = "password";
+ expect_churl_headers("X-GP-REMOTE-PASS", pxf_remote_service_secret);
+
+ build_http_header(input_data);
+}
+
+void
+test__build_http_header__remote_credentials_are_not_null(void **state)
+{
+ expect_external_vars();
+
+ expect_churl_headers("X-GP-SEGMENT-ID", mock_extvar->GP_SEGMENT_ID);
+ expect_churl_headers("X-GP-SEGMENT-COUNT", mock_extvar->GP_SEGMENT_COUNT);
+ expect_churl_headers("X-GP-XID", mock_extvar->GP_XID);
+ expect_churl_headers_alignment();
+ expect_churl_headers("X-GP-URL-HOST", gphd_uri->host);
+ expect_churl_headers("X-GP-URL-PORT", gphd_uri->port);
+ expect_churl_headers("X-GP-DATA-DIR", gphd_uri->data);
+ expect_churl_headers("X-GP-URI", gphd_uri->uri);
+ expect_churl_headers("X-GP-HAS-FILTER", "0");
+
+ pxf_remote_service_login = "not a valid login";
+ expect_churl_headers("X-GP-REMOTE-USER", pxf_remote_service_login);
+
+ pxf_remote_service_secret = "password";
+ expect_churl_headers("X-GP-REMOTE-PASS", pxf_remote_service_secret);
+
+ build_http_header(input_data);
+}
+
+/*
+ * Add an expect clause on a churl_headers_append with given
+ * key and value
+ */
+void
+expect_churl_headers(const char *key, const char *value)
+{
+ expect_value(churl_headers_append, headers, input_data->headers);
+ expect_string(churl_headers_append, key, key);
+ expect_string(churl_headers_append, value, value);
+ will_be_called(churl_headers_append);
+}
+
+/*
+ * Add the X-GP-ALIGNMENT header
+ * As I don't want to copy-paste the logic in the
+ * production code I just support two cases.
+ * Anything other than that requires special attention
+ */
+void
+expect_churl_headers_alignment()
+{
+ if (sizeof(char*) == 4)
+ expect_churl_headers("X-GP-ALIGNMENT", "4");
+ else if (sizeof(char*) == 8)
+ expect_churl_headers("X-GP-ALIGNMENT", "8");
+ else
+ assert_false(true);
+}
+
+void
+common_setup (void** state)
+{
+ store_gucs();
+ setup_gphd_uri();
+ setup_input_data();
+ setup_external_vars();
+}
+
+void
+store_gucs()
+{
+ old_pxf_remote_service_login = pxf_remote_service_login;
+ old_pxf_remote_service_secret = pxf_remote_service_secret;
+}
+
+void
+setup_gphd_uri()
+{
+ gphd_uri = palloc0(sizeof(GPHDUri));
+ gphd_uri->host = "there's a place you're always welcome";
+ gphd_uri->port = "it's as nice as it can be";
+ gphd_uri->data = "everyone can get in";
+ gphd_uri->uri = "'cos it's absolutely free";
+}
+
+void
+setup_input_data()
+{
+ input_data = palloc0(sizeof(PxfInputData));
+ input_data->gphduri = gphd_uri;
+ input_data->headers = 0xBAADF00D;
+}
+
+void
+setup_external_vars()
+{
+ mock_extvar = palloc0(sizeof(extvar_t));
+
+ snprintf(mock_extvar->GP_SEGMENT_ID, sizeof(mock_extvar->GP_SEGMENT_ID), "badID");
+ snprintf(mock_extvar->GP_SEGMENT_COUNT, sizeof(mock_extvar->GP_SEGMENT_COUNT), "lots");
+ snprintf(mock_extvar->GP_XID, sizeof(mock_extvar->GP_XID), "badXID");
+}
+
+void expect_external_vars()
+{
+ expect_any(external_set_env_vars, extvar);
+ expect_string(external_set_env_vars, uri, gphd_uri->uri);
+ expect_value(external_set_env_vars, csv, false);
+ expect_value(external_set_env_vars, escape, NULL);
+ expect_value(external_set_env_vars, quote, NULL);
+ expect_value(external_set_env_vars, header, false);
+ expect_value(external_set_env_vars, scancounter, 0);
+ will_assign_memory(external_set_env_vars, extvar, mock_extvar, sizeof(extvar_t));
+ will_be_called(external_set_env_vars);
+}
+
+/*
+ * Common resource cleanup
+ */
+void
+common_teardown (void** state)
+{
+ pfree(mock_extvar);
+ pfree(input_data);
+ pfree(gphd_uri);
+
+ // Reset GUCs so tests won't have to
+ restore_gucs();
+}
+
+void restore_gucs()
+{
+ pxf_remote_service_login = old_pxf_remote_service_login;
+ pxf_remote_service_secret = old_pxf_remote_service_secret;
+}
+
+int
+main(int argc, char* argv[])
+{
+ cmockery_parse_arguments(argc, argv);
+
+ const UnitTest tests[] =
+ {
+ unit_test_setup_teardown(test__build_http_header__remote_login_is_null,
+ common_setup, common_teardown),
+ unit_test_setup_teardown(test__build_http_header__remote_login_is_not_null,
+ common_setup, common_teardown),
+ unit_test_setup_teardown(test__build_http_header__remote_credentials_are_not_null,
+ common_setup, common_teardown)
+ };
+
+ return run_tests(tests);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test/pxfmasterapi_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test/pxfmasterapi_test.c b/src/backend/access/external/test/pxfmasterapi_test.c
new file mode 100644
index 0000000..f28fd09
--- /dev/null
+++ b/src/backend/access/external/test/pxfmasterapi_test.c
@@ -0,0 +1,231 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include "cmockery.h"
+
+#include "c.h"
+#include "../pxfmasterapi.c"
+#include "lib/stringinfo.h"
+#include "utils/elog.h"
+#include <stdarg.h>
+
+/*
+ * Tests for the HA failover mechanism
+ * pxfmasterapi.c contains several methods that issue REST calls to the PXF agent:
+ * get_data_fragment_list(), get_datanode_rest_servers() and get_data_statistics()
+ * All these methods need to support the case where PXF is deployed on a HA HDFS namenode cluster.
+ * In such a situation a namenode machine is actually represented by two machines and
+ * one of them could become inactive.
+ * For this reason the REST logic was encapsulated into a failover logic in function rest_request().
+ * All REST calls mentioned above will use rest_request(). The tests bellow will validate rest_request().
+ */
+
+/*
+ * Trigger the first exception thrown from rest_request
+ * Function is used with will_be_called_with_sideeffect
+ */
+void
+FirstException( )
+{
+ elog(ERROR, "first exception");
+}
+
+/*
+ * Trigger the second exception thrown from rest_request
+ * Function is used with will_be_called_with_sideeffect
+ */
+void
+SecondException( )
+{
+ elog(ERROR, "second exception");
+}
+
+/*
+ * SUT: rest_request
+ * call_rest throws an error while not in HA mode
+ */
+void
+test__rest_request__callRestThrowsNoHA(void **state)
+{
+ GPHDUri *hadoop_uri = (GPHDUri*) palloc0(sizeof(GPHDUri));
+ hadoop_uri->host = pstrdup("host1");
+ hadoop_uri->port = pstrdup("port1");
+ ClientContext* client_context = (ClientContext*) palloc0(sizeof(ClientContext));
+ char *restMsg = "empty message";
+
+ expect_any(call_rest, hadoop_uri);
+ expect_any(call_rest, client_context);
+ expect_any(call_rest, rest_msg);
+ will_be_called_with_sideeffect(call_rest, &FirstException, NULL);
+
+ /* test */
+ PG_TRY();
+ {
+ rest_request(hadoop_uri, client_context, restMsg);
+ }
+ PG_CATCH();
+ {
+ pfree(hadoop_uri->host);
+ pfree(hadoop_uri->port);
+ pfree(hadoop_uri);
+ pfree(client_context);
+
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_string_equal(edata->message, "first exception");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * SUT: rest_request
+ * call_rest throws an error while in HA mode
+ * and the failover method finds an active IP so the second
+ * call to call_rest does no throw an exception
+ */
+void
+test__rest_request__callRestThrowsHAFirstTime(void **state)
+{
+ GPHDUri *hadoop_uri = (GPHDUri*) palloc0(sizeof(GPHDUri));
+ hadoop_uri->host = pstrdup("host1");
+ hadoop_uri->port = pstrdup("port1");
+ NNHAConf *ha_nodes = (NNHAConf*) palloc0(sizeof(NNHAConf));
+ hadoop_uri->ha_nodes = ha_nodes;
+ ha_nodes->nodes = (char *[]){"host1", "host2"};
+ ha_nodes->restports = (char *[]){"port1", "port2"};
+ ha_nodes->numn = 2;
+
+ ClientContext* client_context = (ClientContext*) palloc0(sizeof(ClientContext));
+ char *restMsg = "empty message";
+
+ expect_any(call_rest, hadoop_uri);
+ expect_any(call_rest, client_context);
+ expect_any(call_rest, rest_msg);
+ will_be_called_with_sideeffect(call_rest, &FirstException, NULL);
+
+ /* the second call from ha_failover */
+ expect_any(call_rest, hadoop_uri);
+ expect_any(call_rest, client_context);
+ expect_any(call_rest, rest_msg);
+ will_be_called(call_rest);
+
+
+ /* test */
+ rest_request(hadoop_uri, client_context, restMsg);
+
+ pfree(hadoop_uri);
+ pfree(client_context);
+}
+
+/*
+ * SUT: rest_request
+ * call_rest throws an error while in HA mode
+ * and the failover method finds an an active IP so the second
+ * call to call_rest is issued on the second IP. This call also throws
+ * an exception - but this time the exception is not caught.
+ */
+void
+test__rest_request__callRestThrowsHASecondTime(void **state)
+{
+ GPHDUri *hadoop_uri = (GPHDUri*) palloc0(sizeof(GPHDUri));
+ hadoop_uri->host = pstrdup("host1");
+ hadoop_uri->port = pstrdup("port1");
+ NNHAConf *ha_nodes = (NNHAConf*) palloc0(sizeof(NNHAConf));
+ hadoop_uri->ha_nodes = ha_nodes;
+ ha_nodes->nodes = (char *[]){"host1", "host2"};
+ ha_nodes->restports = (char *[]){"port1", "port2"};
+ ha_nodes->numn = 2;
+
+ ClientContext* client_context = (ClientContext*) palloc0(sizeof(ClientContext));
+ char *restMsg = "empty message";
+
+ expect_any(call_rest, hadoop_uri);
+ expect_any(call_rest, client_context);
+ expect_any(call_rest, rest_msg);
+ will_be_called_with_sideeffect(call_rest, &FirstException, NULL);
+
+ /* the second call from ha_failover */
+ expect_any(call_rest, hadoop_uri);
+ expect_any(call_rest, client_context);
+ expect_any(call_rest, rest_msg);
+ will_be_called_with_sideeffect(call_rest, &SecondException, NULL);
+
+
+ /* test */
+ PG_TRY();
+ {
+ rest_request(hadoop_uri, client_context, restMsg);
+ }
+ PG_CATCH();
+ {
+ pfree(hadoop_uri->host);
+ pfree(hadoop_uri->port);
+ pfree(hadoop_uri);
+ pfree(client_context);
+
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_string_equal(edata->message, "second exception");
+ /* the first exception was caught by rest_request() */
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * SUT: rest_request
+ * the first time call_rest is called we succeed, since the first IP is valid
+ * No exceptions are thrown
+ */
+void
+test__rest_request__callRestHASuccessFromTheFirstCall(void **state)
+{
+ GPHDUri *hadoop_uri = (GPHDUri*) palloc0(sizeof(GPHDUri));
+ hadoop_uri->host = pstrdup("host1");
+ hadoop_uri->port = pstrdup("port1");
+ NNHAConf *ha_nodes = (NNHAConf*) palloc0(sizeof(NNHAConf));
+ hadoop_uri->ha_nodes = ha_nodes;
+ ha_nodes->nodes = (char *[]){"host1", "host2"};
+ ha_nodes->restports = (char *[]){"port1", "port2"};
+ ha_nodes->numn = 2;
+
+ ClientContext* client_context = (ClientContext*) palloc0(sizeof(ClientContext));
+ char *restMsg = "empty message";
+
+ expect_any(call_rest, hadoop_uri);
+ expect_any(call_rest, client_context);
+ expect_any(call_rest, rest_msg);
+ will_be_called(call_rest);
+
+ /* test */
+ rest_request(hadoop_uri, client_context, restMsg);
+
+ pfree(hadoop_uri->host);
+ pfree(hadoop_uri->port);
+ pfree(hadoop_uri);
+ pfree(client_context);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ cmockery_parse_arguments(argc, argv);
+
+ const UnitTest tests[] = {
+ unit_test(test__rest_request__callRestThrowsNoHA),
+ unit_test(test__rest_request__callRestThrowsHAFirstTime),
+ unit_test(test__rest_request__callRestThrowsHASecondTime),
+ unit_test(test__rest_request__callRestHASuccessFromTheFirstCall)
+ };
+ return run_tests(tests);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test/pxfuriparser_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test/pxfuriparser_test.c b/src/backend/access/external/test/pxfuriparser_test.c
new file mode 100644
index 0000000..ecde5aa
--- /dev/null
+++ b/src/backend/access/external/test/pxfuriparser_test.c
@@ -0,0 +1,352 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include "cmockery.h"
+
+#include "c.h"
+#include "../pxfuriparser.c"
+
+
+/*
+ * Test parsing of valid uri as given in LOCATION in a PXF external table.
+ */
+void
+test__parseGPHDUri__ValidURI(void **state)
+{
+ char* uri = "pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=SomeFragmenter&ACCESSOR=SomeAccessor&RESOLVER=SomeResolver&ANALYZER=SomeAnalyzer";
+ List* options = NIL;
+ ListCell* cell = NULL;
+ OptionData* option = NULL;
+
+ GPHDUri* parsed = parseGPHDUri(uri);
+
+ assert_true(parsed != NULL);
+ assert_string_equal(parsed->uri, uri);
+
+ assert_string_equal(parsed->protocol, "pxf");
+ assert_string_equal(parsed->host, "1.2.3.4");
+ assert_string_not_equal(parsed->port, "5678"); /* it should be pxf_service_port */
+ assert_string_equal(parsed->data, "some/path/and/table.tbl");
+
+ options = parsed->options;
+ assert_int_equal(list_length(options), 4);
+
+ cell = list_nth_cell(options, 0);
+ option = lfirst(cell);
+ assert_string_equal(option->key, "FRAGMENTER");
+ assert_string_equal(option->value, "SomeFragmenter");
+
+ cell = list_nth_cell(options, 1);
+ option = lfirst(cell);
+ assert_string_equal(option->key, "ACCESSOR");
+ assert_string_equal(option->value, "SomeAccessor");
+
+ cell = list_nth_cell(options, 2);
+ option = lfirst(cell);
+ assert_string_equal(option->key, "RESOLVER");
+ assert_string_equal(option->value, "SomeResolver");
+
+ cell = list_nth_cell(options, 3);
+ option = lfirst(cell);
+ assert_string_equal(option->key, "ANALYZER");
+ assert_string_equal(option->value, "SomeAnalyzer");
+
+ assert_true(parsed->fragments == NULL);
+
+ freeGPHDUri(parsed);
+}
+
+/*
+ * Negative test: parsing of uri without protocol delimiter "://"
+ */
+void
+test__parseGPHDUri__NegativeTestNoProtocol(void **state)
+{
+ char* uri_no_protocol = "pxf:/1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=HdfsDataFragmenter";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri* parsed = parseGPHDUri(uri_no_protocol);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf:/1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=HdfsDataFragmenter");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Negative test: parsing of uri without options part
+ */
+void
+test__parseGPHDUri__NegativeTestNoOptions(void **state)
+{
+ char* uri_no_options = "pxf://1.2.3.4:5678/some/path/and/table.tbl";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri* parsed = parseGPHDUri(uri_no_options);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl: missing options section");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Negative test: parsing of a uri with a missing equal
+ */
+void
+test__parseGPHDUri__NegativeTestMissingEqual(void **state)
+{
+ char* uri_missing_equal = "pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri* parsed = parseGPHDUri(uri_missing_equal);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER: option 'FRAGMENTER' missing '='");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Negative test: parsing of a uri with duplicate equals
+ */
+void
+test__parseGPHDUri__NegativeTestDuplicateEquals(void **state)
+{
+ char* uri_duplicate_equals = "pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=HdfsDataFragmenter=DuplicateFragmenter";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri* parsed = parseGPHDUri(uri_duplicate_equals);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=HdfsDataFragmenter=DuplicateFragmenter: option 'FRAGMENTER=HdfsDataFragmenter=DuplicateFragmenter' contains duplicate '='");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Negative test: parsing of a uri with a missing key
+ */
+void
+test__parseGPHDUri__NegativeTestMissingKey(void **state)
+{
+ char* uri_missing_key = "pxf://1.2.3.4:5678/some/path/and/table.tbl?=HdfsDataFragmenter";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri* parsed = parseGPHDUri(uri_missing_key);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl?=HdfsDataFragmenter: option '=HdfsDataFragmenter' missing key before '='");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Negative test: parsing of a uri with a missing value
+ */
+void
+test__parseGPHDUri__NegativeTestMissingValue(void **state)
+{
+ char* uri_missing_value = "pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri* parsed = parseGPHDUri(uri_missing_value);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=: option 'FRAGMENTER=' missing value after '='");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Test GPHDUri_verify_no_duplicate_options: valid uri
+ */
+void
+test__GPHDUri_verify_no_duplicate_options__ValidURI(void **state)
+{
+ char* valid_uri = "pxf://1.2.3.4:5678/some/path/and/table.tbl?Profile=a&Analyzer=b";
+
+ /* Setting the test -- code omitted -- */
+ GPHDUri* parsed = parseGPHDUri(valid_uri);
+ GPHDUri_verify_no_duplicate_options(parsed);
+ freeGPHDUri(parsed);
+}
+
+/*
+ * Negative test of GPHDUri_verify_no_duplicate_options: parsing of a uri with duplicate options
+ */
+void
+test__GPHDUri_verify_no_duplicate_options__NegativeTestDuplicateOpts(void **state)
+{
+ char* uri_duplicate_opts = "pxf://1.2.3.4:5678/some/path/and/table.tbl?Profile=a&Analyzer=b&PROFILE=c";
+
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ GPHDUri* parsed = parseGPHDUri(uri_duplicate_opts);
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri_verify_no_duplicate_options(parsed);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl?Profile=a&Analyzer=b&PROFILE=c: Duplicate option(s): PROFILE");
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+/*
+ * Test GPHDUri_verify_core_options_exist with a valid uri
+ */
+void
+test__GPHDUri_verify_core_options_exist__ValidURI(void **state)
+{
+ char* valid_uri = "pxf://1.2.3.4:5678/some/path/and/table.tbl?Fragmenter=1&Accessor=2&Resolver=3";
+
+ /* Setting the test -- code omitted -- */
+ GPHDUri* parsed = parseGPHDUri(valid_uri);
+ List *coreOptions = list_make3("FRAGMENTER", "ACCESSOR", "RESOLVER");
+ GPHDUri_verify_core_options_exist(parsed, coreOptions);
+ freeGPHDUri(parsed);
+ list_free(coreOptions);
+}
+
+/*
+ * Negative test of GPHDUri_verify_core_options_exist: Missing core options
+ */
+void
+test__GPHDUri_verify_core_options_exist__NegativeTestMissingCoreOpts(void **state)
+{
+ char* missing_core_opts = "pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=a";
+ List *coreOptions;
+ /* Setting the test -- code omitted -- */
+ PG_TRY();
+ {
+ GPHDUri* parsed = parseGPHDUri(missing_core_opts);
+ coreOptions = list_make3("FRAGMENTER", "ACCESSOR", "RESOLVER");
+ /* This will throw a ereport(ERROR).*/
+ GPHDUri_verify_core_options_exist(parsed, coreOptions);
+ }
+ PG_CATCH();
+ {
+ CurrentMemoryContext = 1;
+ ErrorData *edata = CopyErrorData();
+
+ /*Validate the type of expected error */
+ assert_true(edata->sqlerrcode == ERRCODE_SYNTAX_ERROR);
+ assert_true(edata->elevel == ERROR);
+ assert_string_equal(edata->message, "Invalid URI pxf://1.2.3.4:5678/some/path/and/table.tbl?FRAGMENTER=a: PROFILE or ACCESSOR and RESOLVER option(s) missing");
+ list_free(coreOptions);
+ return;
+ }
+ PG_END_TRY();
+
+ assert_true(false);
+}
+
+int
+main(int argc, char* argv[])
+{
+ cmockery_parse_arguments(argc, argv);
+
+ const UnitTest tests[] = {
+ unit_test(test__parseGPHDUri__ValidURI),
+ unit_test(test__parseGPHDUri__NegativeTestNoProtocol),
+ unit_test(test__parseGPHDUri__NegativeTestNoOptions),
+ unit_test(test__parseGPHDUri__NegativeTestMissingEqual),
+ unit_test(test__parseGPHDUri__NegativeTestDuplicateEquals),
+ unit_test(test__parseGPHDUri__NegativeTestMissingKey),
+ unit_test(test__parseGPHDUri__NegativeTestMissingValue),
+ unit_test(test__GPHDUri_verify_no_duplicate_options__ValidURI),
+ unit_test(test__GPHDUri_verify_no_duplicate_options__NegativeTestDuplicateOpts),
+ unit_test(test__GPHDUri_verify_core_options_exist__ValidURI),
+ unit_test(test__GPHDUri_verify_core_options_exist__NegativeTestMissingCoreOpts)
+ };
+ return run_tests(tests);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test_discard/.gitignore
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test_discard/.gitignore b/src/backend/access/external/test_discard/.gitignore
deleted file mode 100644
index a8d6b6c..0000000
--- a/src/backend/access/external/test_discard/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.t
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test_discard/Makefile
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test_discard/Makefile b/src/backend/access/external/test_discard/Makefile
deleted file mode 100644
index e13d107..0000000
--- a/src/backend/access/external/test_discard/Makefile
+++ /dev/null
@@ -1,66 +0,0 @@
-subdir=src/backend/access/external
-top_builddir=../../../../..
-
-TARGETS=pxfuriparser hd_work_mgr pxfheaders ha_config pxffilters pxfmasterapi
-
-# Objects from backend, which don't need to be mocked but need to be linked.
-COMMON_REAL_OBJS=\
- $(top_srcdir)/src/backend/access/hash/hashfunc.o \
- $(top_srcdir)/src/backend/bootstrap/bootparse.o \
- $(top_srcdir)/src/backend/lib/stringinfo.o \
- $(top_srcdir)/src/backend/nodes/bitmapset.o \
- $(top_srcdir)/src/backend/nodes/equalfuncs.o \
- $(top_srcdir)/src/backend/nodes/list.o \
- $(top_srcdir)/src/backend/parser/gram.o \
- $(top_srcdir)/src/backend/regex/regcomp.o \
- $(top_srcdir)/src/backend/regex/regerror.o \
- $(top_srcdir)/src/backend/regex/regexec.o \
- $(top_srcdir)/src/backend/regex/regfree.o \
- $(top_srcdir)/src/backend/storage/page/itemptr.o \
- $(top_srcdir)/src/backend/utils/adt/datum.o \
- $(top_srcdir)/src/backend/utils/adt/like.o \
- $(top_srcdir)/src/backend/utils/error/elog.o \
- $(top_srcdir)/src/backend/utils/hash/dynahash.o \
- $(top_srcdir)/src/backend/utils/hash/hashfn.o \
- $(top_srcdir)/src/backend/utils/init/globals.o \
- $(top_srcdir)/src/backend/utils/mb/mbutils.o \
- $(top_srcdir)/src/backend/utils/mb/wchar.o \
- $(top_srcdir)/src/backend/utils/misc/guc.o \
- $(top_srcdir)/src/port/exec.o \
- $(top_srcdir)/src/port/path.o \
- $(top_srcdir)/src/port/pgsleep.o \
- $(top_srcdir)/src/port/pgstrcasecmp.o \
- $(top_srcdir)/src/port/qsort.o \
- $(top_srcdir)/src/port/strlcpy.o \
- $(top_srcdir)/src/port/thread.o \
- $(top_srcdir)/src/timezone/localtime.o \
- $(top_srcdir)/src/timezone/pgtz.o \
- $(top_srcdir)/src/timezone/strftime.o \
- $(top_srcdir)/src/backend/utils/mmgr/redzone_handler.o \
-
-# Objects from backend, which don't need to be mocked but need to be linked.
-pxfuriparser_REAL_OBJS=$(COMMON_REAL_OBJS) \
- $(top_srcdir)/src/backend/utils/adt/formatting.o \
- $(top_srcdir)/src/backend/nodes/value.o \
- $(top_srcdir)/src/backend/utils/adt/numutils.o \
- $(top_srcdir)/src/backend/access/external/pxfutils.o
-hd_work_mgr_REAL_OBJS=$(COMMON_REAL_OBJS) \
- $(top_srcdir)/src/backend/cdb/cdbutil.o \
- $(top_srcdir)/src/backend/access/external/pxfuriparser.o \
- $(top_srcdir)/src/backend/access/external/pxfutils.o
-
-# numutils for pg_ltoa
-pxfheaders_REAL_OBJS=$(COMMON_REAL_OBJS) \
- $(top_srcdir)/src/backend/utils/adt/numutils.o
-ha_config_REAL_OBJS=$(COMMON_REAL_OBJS) \
- $(top_srcdir)/src/backend/utils/fmgrtab.o \
- $(top_srcdir)/src/backend/utils/adt/numutils.o
-pxfmasterapi_REAL_OBJS=$(COMMON_REAL_OBJS) \
- $(top_srcdir)/src/backend/utils/fmgrtab.o
-pxffilters_REAL_OBJS=$(COMMON_REAL_OBJS) \
- $(top_srcdir)/src/backend/optimizer/util/clauses.o \
- $(top_srcdir)/src/backend/parser/parse_expr.o
-
-include ../../../../Makefile.mock
-
-MOCK_LIBS += -ljson
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test_discard/README.txt
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test_discard/README.txt b/src/backend/access/external/test_discard/README.txt
deleted file mode 100644
index 75a03f0..0000000
--- a/src/backend/access/external/test_discard/README.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Directory with the following System Under Test (SUT):
- - pxfuriparser.c
- - hd_work_mgr.c
- - pxfheaders.c
- - ha_config.c
- - pxffilters.c
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test_discard/ha_config_mock.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test_discard/ha_config_mock.c b/src/backend/access/external/test_discard/ha_config_mock.c
deleted file mode 100644
index dcf2b12..0000000
--- a/src/backend/access/external/test_discard/ha_config_mock.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <stdarg.h>
-#include <stddef.h>
-#include <setjmp.h>
-#include "cmockery.h"
-
-#include "c.h"
-#include "hdfs/hdfs.h"
-
-/* Mock functions for the hdfs.h APIs used by load_nn_ha_config() in ha_config.c */
-
-Namenode * hdfsGetHANamenodes(const char *nameservice, int *size)
-{
- optional_assignment(size);
- return (Namenode *)mock();
-}
-
-void hdfsFreeNamenodeInformation(Namenode *namenodes, int size)
-{
- mock();
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test_discard/ha_config_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test_discard/ha_config_test.c b/src/backend/access/external/test_discard/ha_config_test.c
deleted file mode 100644
index 61cf1de..0000000
--- a/src/backend/access/external/test_discard/ha_config_test.c
+++ /dev/null
@@ -1,419 +0,0 @@
-#include <stdarg.h>
-#include <stddef.h>
-#include <setjmp.h>
-#include "cmockery.h"
-
-#include "c.h"
-#include "../ha_config.c"
-#include "ha_config_mock.c"
-#include "lib/stringinfo.h"
-#include "utils/builtins.h"
-
-/* Helper functions signature */
-#define format_string_release(p) (pfree(p))
-
-static char *format_string_create(char *f,...);
-static void handle_pg_excp(char *msg, int errcode);
-
-/*
- * Unitest for GPHD_HA_load_nodes() in ../access/external/ha_config.c
- * GPHD_HA_load_nodes() discovers the active Namnode from an HA Namenodes pair.
- * It does this by interacting with the API exposed by hdfs.h, from which it uses
- * 2 functions:
- * a. Namenode * hdfsGetHANamenodes(const char * nameservice, int * size);
- * b. void hdfsFreeNamenodeInformation(Namenode * namenodes, int size);
- * This unitest verifies the correct interaction between GPHD_HA_load_nodes() implementation
- * and the 2 hdfs.h APIs. It looks at the standard flows with expected input configuration
- * and also at limit cases with corrupted input configuration.
- * The mock functions for the two(2) hdfs.h APIs are in ha_config_mock.c.
- */
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice);
- * Mock function: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * Negative test: GPHD_HA_load_nodes() receives an unexistent namesrvice
- */
-void
-test__GPHD_HA_load_nodes__UnknownNameservice(void **state)
-{
- /*
- * In case it receives an unknown nameservice string, the real function hdfsGetHANamenodes()
- * will return NULL. We instruct our mock function to return NULL. In this way we simulate
- * an unknown_service scenario and verify that our SUT function GPHD_HA_load_nodes() handles
- * correctly the NULL returned by hdfsGetHANamenodes.
- */
- will_return(hdfsGetHANamenodes, NULL);
-
- PG_TRY();
- {
- NNHAConf *hac = GPHD_HA_load_nodes("UNKNOWN_SERVICE");
- }
- PG_CATCH();
- {
- char *msg = "nameservice UNKNOWN_SERVICE not found in client configuration. No HA namenodes provided";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-
- assert_true(false);
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice);
- * Mock function: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * Negative test: hdfsGetHANamenodes() returns just one namenode.
- * This is not an HA sustainable.
- */
-void
-test__GPHD_HA_load_nodes__OneNN(void **state)
-{
- unsigned int numn = 1;
- Namenode nns[1];
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
-
- PG_TRY();
- {
- NNHAConf *hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = format_string_create("High availability for nameservice %s was configured with only one node. A high availability scheme requires at least two nodes ",
- "NAMESERVICE");
- handle_pg_excp(msg, ERRCODE_INTERNAL_ERROR);
- format_string_release(msg); /* if we trip on assert_string_equal we don't free but it doesen't matter because process stops*/
- return;
- }
- PG_END_TRY();
-
- assert_true(false);
-
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice);
- * Mock function: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * Negative test: hdfsGetHANamenodes() returns a Namenode.rpc_address field without ":"
- * the host:port delimiter.
- */
-void
-test__GPHD_HA_load_nodes__RpcDelimMissing(void **state)
-{
- unsigned int numn = 2;
- Namenode nns[] = { {"mdw2080", "mdw:50070"}, {"smdw:2080", "smdw:50070"}};
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- PG_TRY();
- {
- NNHAConf *hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = "dfs.namenode.rpc-address was set incorrectly in the configuration. ':' missing";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-
- assert_true(false);
-
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice)
- * Mock functions: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * void port_to_str(char **port, int new_port)
- * Positive test: port_to_str() assigns pxf_service_port correctly
- */
-void
-test__GPHD_HA_load_nodes__PxfServicePortIsAssigned(void **state)
-{
- unsigned int numn = 2;
- Namenode nns[] = { {"mdw:2080", "mdw:50070"}, {"smdw:2080", "smdw:50070"}};
- char strPort[30] = {0};
- pg_ltoa(pxf_service_port, strPort);
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, strPort);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, strPort);
-
- will_be_called(hdfsFreeNamenodeInformation);
-
-
- NNHAConf *hac = GPHD_HA_load_nodes("NAMESERVICE");
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice)
- * Mock functions: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * void port_to_str(char **port, int new_port)
- * Negative test: hdfsGetHANamenodes() returns a Namenode.http_address field without
- * the host - ":port".
- */
-void
-test__GPHD_HA_load_nodes__HostMissing(void **state)
-{
- unsigned int numn = 2;
- Namenode nns[] = { {":2080", "mdw:50070"}, {"smdw:2080", "smdw:50070"}};
- char strPort[30] = {0};
- pg_ltoa(pxf_service_port, strPort);
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, strPort);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, strPort);
-
- will_be_called(hdfsFreeNamenodeInformation);
-
- PG_TRY();
- {
- NNHAConf *hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = "HA Namenode host number 1 is NULL value";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice)
- * Mock functions: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * void port_to_str(char **port, int new_port)
- * Negative test: port_to_str() does not set the port
- * the port - "host:".
- */
-void
-test__GPHD_HA_load_nodes__PortMissing(void **state)
-{
- unsigned int numn = 2;
- Namenode nns[] = { {"mdw:", "mdw:50070"}, {"smdw:2080", "smdw:50070"}};
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
-
- will_be_called(hdfsFreeNamenodeInformation);
-
- PG_TRY();
- {
- NNHAConf *hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = "HA Namenode RPC port number 1 is NULL value";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice)
- * Mock functions: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * void port_to_str(char **port, int new_port)
- * Negative test: port_to_str() returns a port outside the valid range
- * - a number higher than 65535
- */
-void
-test__GPHD_HA_load_nodes__PortIsInvalidNumber(void **state)
-{
- unsigned int numn = 2;
- Namenode nns[] = { {"mdw:2080", "mdw:65550"}, {"smdw:2080", "smdw:50070"}};
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, "65550");
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, "65550");
-
- will_be_called(hdfsFreeNamenodeInformation);
-
- PG_TRY();
- {
- NNHAConf *hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = "Invalid port <65550> detected in nameservice configuration";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice)
- * Mock functions: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * void port_to_str(char **port, int new_port)
- * Negative test: port_to_str() returns a port that is not a number
- */
-void
-test__GPHD_HA_load_nodes__PortIsNotNumber_TakeOne(void **state)
-{
- NNHAConf *hac;
- unsigned int numn = 2;
- Namenode nns[] = { {"mdw:2080", "mdw:50070"}, {"smdw:2080", "smdw:50070"}};
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, "melon");
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
-
- will_be_called(hdfsFreeNamenodeInformation);
-
- PG_TRY();
- {
- hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = "Invalid port <melon> detected in nameservice configuration";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-}
-
-/*
- * SUT function: NNHAConf* GPHD_HA_load_nodes(const char *nameservice)
- * Mock functions: Namenode * hdfsGetHANamenodes(const char * nameservice, int * size)
- * void port_to_str(char **port, int new_port)
- * Negative test: port_to_str() returns a port that is not a number
- */
-void
-test__GPHD_HA_load_nodes__PortIsNotNumber_TakeTwo(void **state)
-{
- NNHAConf *hac;
- unsigned int numn = 2;
- Namenode nns[] = { {"mdw:2080", "mdw:50070"}, {"smdw:2080", "smdw:50070"}};
-
- will_return(hdfsGetHANamenodes, nns);
- will_assign_value(hdfsGetHANamenodes, size, numn);
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
- will_assign_string(port_to_str, port, "100ab");
-
- will_be_called(port_to_str);
- expect_not_value(port_to_str, port, NULL);
- expect_value(port_to_str, new_port, pxf_service_port);
-
- will_be_called(hdfsFreeNamenodeInformation);
-
- PG_TRY();
- {
- hac = GPHD_HA_load_nodes("NAMESERVICE");
- }
- PG_CATCH();
- {
- char *msg = "Invalid port <100ab> detected in nameservice configuration";
- handle_pg_excp(msg, ERRCODE_SYNTAX_ERROR);
- return;
- }
- PG_END_TRY();
-}
-
-int
-main(int argc, char *argv[])
-{
- cmockery_parse_arguments(argc, argv);
-
- const UnitTest tests[] = {
- unit_test(test__GPHD_HA_load_nodes__UnknownNameservice),
- unit_test(test__GPHD_HA_load_nodes__OneNN),
- unit_test(test__GPHD_HA_load_nodes__RpcDelimMissing),
- unit_test(test__GPHD_HA_load_nodes__PxfServicePortIsAssigned),
- unit_test(test__GPHD_HA_load_nodes__HostMissing),
- unit_test(test__GPHD_HA_load_nodes__PortMissing),
- unit_test(test__GPHD_HA_load_nodes__PortIsInvalidNumber),
- unit_test(test__GPHD_HA_load_nodes__PortIsNotNumber_TakeOne),
- unit_test(test__GPHD_HA_load_nodes__PortIsNotNumber_TakeTwo)
- };
- return run_tests(tests);
-}
-
-/*
- * Helper function to format strings that need to be passed to assert macros
- */
-static char*
-format_string_create(char *f,...)
-{
- StringInfoData s;
- va_list vl;
-
- initStringInfo(&s);
-
- va_start(vl,f);
- appendStringInfoVA(&s, f, vl);
- va_end(vl);
-
- return s.data;
-}
-
-/*
- * Encapsulates exception unpackaging
- */
-static void
-handle_pg_excp(char *msg, int errcode)
-{
- CurrentMemoryContext = 1;
- ErrorData *edata = CopyErrorData();
-
- assert_true(edata->sqlerrcode == errcode);
- assert_true(edata->elevel == ERROR);
- assert_string_equal(edata->message, msg);
-
- /* Clean the internal error data stack. Otherwise errordata_stack_depth in elog.c,
- * keeps growing from test to test with each ereport we issue in our SUT function
- * until we reach errordata_stack_depth >= ERRORDATA_STACK_SIZE and our tests
- * start failing
- */
- elog_dismiss(INFO);
-}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7c2f615d/src/backend/access/external/test_discard/hd_work_mgr_allocate_fragments_to_datanodes_test.c
----------------------------------------------------------------------
diff --git a/src/backend/access/external/test_discard/hd_work_mgr_allocate_fragments_to_datanodes_test.c b/src/backend/access/external/test_discard/hd_work_mgr_allocate_fragments_to_datanodes_test.c
deleted file mode 100644
index fb42ee1..0000000
--- a/src/backend/access/external/test_discard/hd_work_mgr_allocate_fragments_to_datanodes_test.c
+++ /dev/null
@@ -1,597 +0,0 @@
-#include <stdarg.h>
-#include <stddef.h>
-#include <setjmp.h>
-#include "cmockery.h"
-
-#include "c.h"
-#include "hd_work_mgr_mock.h"
-
-
-/*
- * check that datanode dn has the expected
- * ip, port, dn blocks list, and number of read & residing fragments
- */
-void check_dn_load(DatanodeProcessingLoad* dn,
- const char* expected_hostip,
- int expected_port,
- List* expected_blocks,
- int expected_read_fragments,
- int expected_residing_fragments)
-{
-
- ListCell* cell = NULL;
- int blocks_number = 0;
-
- assert_string_equal(dn->dataNodeIp, expected_hostip);
- assert_int_equal(dn->port, expected_port);
- assert_int_equal(dn->num_fragments_read, expected_read_fragments);
- assert_int_equal(dn->num_fragments_residing, expected_residing_fragments);
-
- assert_int_equal(list_length(expected_blocks), list_length(dn->datanodeBlocks));
- blocks_number = list_length(expected_blocks);
- for (int i = 0; i < blocks_number; ++i)
- {
- AllocatedDataFragment* block =
- (AllocatedDataFragment*)lfirst(list_nth_cell(dn->datanodeBlocks, i));
- AllocatedDataFragment* expected_block =
- (AllocatedDataFragment*)lfirst(list_nth_cell(expected_blocks, i));
- assert_string_equal(block->host, expected_block->host);
- assert_int_equal(block->rest_port, expected_block->rest_port);
- assert_string_equal(block->source_name, expected_block->source_name);
- assert_string_equal(block->fragment_md, expected_block->fragment_md);
- assert_string_equal(block->user_data, expected_block->user_data);
- assert_int_equal(block->index, expected_block->index);
- }
-
-}
-
-/*
- * Test get_dn_processing_load:
- * starting with an empty list, add fragment location
- * and check that the returned element equals the given fragment
- * and that if the location is new a new element was added to the list.
- */
-void
-test__get_dn_processing_load(void **state)
-{
- List* allDNProcessingLoads = NIL;
- ListCell* cell = NULL;
- FragmentHost *fragment_loc = NULL;
- DatanodeProcessingLoad* dn_found = NULL;
-
- char* ip_array[] =
- {
- "1.2.3.1",
- "1.2.3.2",
- "1.2.3.3",
- "1.2.3.1",
- "1.2.3.1",
- "1.2.3.3",
- "1.2.3.1"
- };
- int port_array[] =
- {
- 100,
- 100,
- 100,
- 100,
- 100,
- 100,
- 200
- };
- int expected_list_size[] =
- {
- 1, 2, 3, 3, 3, 3, 4
- };
- int array_size = 7;
- /* sanity */
- assert_int_equal(array_size, (sizeof(ip_array) / sizeof(ip_array[0])));
- assert_int_equal(array_size, (sizeof(port_array) / sizeof(port_array[0])));
- assert_int_equal(array_size, (sizeof(expected_list_size) / sizeof(expected_list_size[0])));
-
- fragment_loc = (FragmentHost*) palloc0(sizeof(FragmentHost));
-
- for (int i = 0; i < array_size; ++i)
- {
- dn_found = NULL;
- fragment_loc->ip = ip_array[i];
- fragment_loc->rest_port = port_array[i];
-
- dn_found = get_dn_processing_load(&allDNProcessingLoads, fragment_loc);
-
- assert_true(dn_found != NULL);
- assert_int_equal(list_length(allDNProcessingLoads), expected_list_size[i]);
-
- check_dn_load(dn_found, ip_array[i], port_array[i], NIL, 0, 0);
- }
-
- pfree(fragment_loc);
- /* free allDNProcessingLoads */
- foreach(cell, allDNProcessingLoads)
- {
- DatanodeProcessingLoad* cell_data = (DatanodeProcessingLoad*)lfirst(cell);
- pfree(cell_data->dataNodeIp);
- }
- list_free(allDNProcessingLoads);
-}
-
-/*
- * create, verify and free AllocatedDataFragment
- */
-void check_create_allocated_fragment(DataFragment* fragment, bool has_user_data)
-{
- AllocatedDataFragment* allocated = create_allocated_fragment(fragment);
-
- assert_true(allocated != NULL);
- assert_int_equal(allocated->index, fragment->index);
- assert_string_equal(allocated->source_name, fragment->source_name);
- assert_string_equal(allocated->fragment_md, fragment->fragment_md);
- if (has_user_data)
- assert_string_equal(allocated->user_data, fragment->user_data);
- else
- assert_true(allocated->user_data == NULL);
- assert_true(allocated->host == NULL);
- assert_int_equal(allocated->rest_port, 0);
-
- if (allocated->source_name)
- pfree(allocated->source_name);
- if (allocated->user_data)
- pfree(allocated->user_data);
- pfree(allocated);
-}
-
-
-/*
- * Test create_allocated_fragment without user_data.
- */
-void
-test__create_allocated_fragment__NoUserData(void **state)
-{
- AllocatedDataFragment* allocated = NULL;
-
- DataFragment* fragment = (DataFragment*) palloc0(sizeof(DataFragment));
- fragment->index = 13;
- fragment->source_name = "source name!!!";
- fragment->user_data = NULL;
- fragment->fragment_md = "METADATA";
-
- check_create_allocated_fragment(fragment, false);
-
- pfree(fragment);
-}
-
-/*
- * Test create_allocated_fragment without user_data.
- */
-void
-test__create_allocated_fragment__WithUserData(void **state)
-{
- AllocatedDataFragment* allocated = NULL;
-
- DataFragment* fragment = (DataFragment*) palloc0(sizeof(DataFragment));
- fragment->index = 13;
- fragment->source_name = "source name!!!";
- fragment->user_data = "Wish You Were Here";
- fragment->fragment_md = "METADATA";
-
- check_create_allocated_fragment(fragment, true);
-
- pfree(fragment);
-}
-
-/*
- * Creates a list of DataFragment for one file ("file.txt").
- * The important thing here is the fragments' location. It is determined by the parameters:
- * replication_factor - number of copies of each fragment on the different hosts.
- * number_of_hosts - number of hosts, so that the IP pool we use is 1.2.3.{1-number_of_hosts}
- * number_of_fragments - number of fragments in the file.
- *
- * Each fragment will have <replication_factor> hosts,
- * starting from IP 1.2.3.<fragment_number> to IP 1.2.3.<fragment_number + replication_factor> modulo <number_of_hosts>.
- * That way there is some overlapping between the hosts of each fragment.
- */
-List* build_data_fragments_list(int number_of_fragments, int number_of_hosts, int replication_factor)
-{
- List* fragments_list = NIL;
- StringInfoData string_info;
- initStringInfo(&string_info);
-
- for (int i = 0; i < number_of_fragments; ++i)
- {
- DataFragment* fragment = (DataFragment*) palloc0(sizeof(DataFragment));
-
- fragment->index = i;
- fragment->source_name = pstrdup("file.txt");
-
- for (int j = 0; j < replication_factor; ++j)
- {
- FragmentHost* fhost = (FragmentHost*)palloc0(sizeof(FragmentHost));
- appendStringInfo(&string_info, "1.2.3.%d", ((j + i) % number_of_hosts) + 1);
- fhost->ip = pstrdup(string_info.data);
- resetStringInfo(&string_info);
- fragment->replicas = lappend(fragment->replicas, fhost);
- }
- assert_int_equal(list_length(fragment->replicas), replication_factor);
- appendStringInfo(&string_info, "metadata %d", i);
- fragment->fragment_md = pstrdup(string_info.data);
- resetStringInfo(&string_info);
- appendStringInfo(&string_info, "user data %d", i);
- fragment->user_data = pstrdup(string_info.data);
- resetStringInfo(&string_info);
- fragments_list = lappend(fragments_list, fragment);
- }
-
- pfree(string_info.data);
- return fragments_list;
-}
-
-/*
- * Returns a list of AllocatedDataFragment.
- */
-List* build_blank_blocks_list(int list_size)
-{
- List* blocks_list = NIL;
- for (int i = 0; i < list_size; ++i)
- {
- AllocatedDataFragment* block = (AllocatedDataFragment*) palloc0(sizeof(AllocatedDataFragment));
- blocks_list = lappend(blocks_list, block);
- }
- return blocks_list;
-}
-
-/*
- * Tests allocate_fragments_to_datanodes with 4 fragments over 10 hosts, with 3 replicates each,
- * so that they are distributed as follows:
- * Fragment 0 : on hosts 1.2.3.1, 1.2.3.2, 1.2.3.3.
- * Fragment 1 : on hosts 1.2.3.2, 1.2.3.3, 1.2.3.4.
- * Fragment 2 : on hosts 1.2.3.3, 1.2.3.4, 1.2.3.5.
- * Fragment 3 : on hosts 1.2.3.4, 1.2.3.5, 1.2.3.6.
- *
- * The expected distribution is as follows:
- * Host 1.2.3.1: fragment 0.
- * Host 1.2.3.2: fragment 1.
- * Host 1.2.3.3: fragment 2.
- * Host 1.2.3.4: fragment 3.
- * Hosts 1.2.3.5, 1.2.3.6: no fragments.
- */
-void
-test__allocate_fragments_to_datanodes__4Fragments10Hosts3Replicates(void **state)
-{
- List* allDNProcessingLoads = NIL;
- List* data_fragment_list = NIL;
- List* blocks_list = NIL;
- ListCell* cell = NULL;
- DatanodeProcessingLoad* datanode_load = NULL;
- AllocatedDataFragment* allocated = NULL;
-
- data_fragment_list = build_data_fragments_list(4, 10, 3);
- assert_int_equal(4, list_length(data_fragment_list));
-
- allDNProcessingLoads = allocate_fragments_to_datanodes(data_fragment_list);
-
- assert_true(allDNProcessingLoads != NULL);
- assert_int_equal(6, list_length(allDNProcessingLoads));
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 0));
- blocks_list = build_blank_blocks_list(1);
- allocated = lfirst(list_nth_cell(blocks_list, 0));
- allocated->host = "1.2.3.1";
- allocated->index = 0;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 0";
- allocated->user_data = "user data 0";
- check_dn_load(datanode_load,
- "1.2.3.1", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 1));
- allocated->host = "1.2.3.2";
- allocated->index = 1;
- allocated->fragment_md = "metadata 1";
- allocated->user_data = "user data 1";
- check_dn_load(datanode_load,
- "1.2.3.2", 0, blocks_list, 1, 2);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 2));
- allocated->host = "1.2.3.3";
- allocated->index = 2;
- allocated->fragment_md = "metadata 2";
- allocated->user_data = "user data 2";
- check_dn_load(datanode_load,
- "1.2.3.3", 0, blocks_list, 1, 3);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 3));
- allocated->host = "1.2.3.4";
- allocated->index = 3;
- allocated->fragment_md = "metadata 3";
- allocated->user_data = "user data 3";
- check_dn_load(datanode_load,
- "1.2.3.4", 0, blocks_list, 1, 3);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 4));
- check_dn_load(datanode_load,
- "1.2.3.5", 0, NIL, 0, 2);
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 5));
- check_dn_load(datanode_load,
- "1.2.3.6", 0, NIL, 0, 1);
-
- /* cleanup */
- list_free(blocks_list);
- foreach (cell, allDNProcessingLoads)
- {
- DatanodeProcessingLoad* dn = (DatanodeProcessingLoad*)lfirst(cell);
- free_allocated_frags(dn->datanodeBlocks);
- }
- list_free(allDNProcessingLoads);
-}
-
-/*
- * Tests allocate_fragments_to_datanodes with 4 fragments over 3 hosts, with 2 replicates each,
- * so that they are distributed as follows:
- * Fragment 0 : on hosts 1.2.3.1, 1.2.3.2.
- * Fragment 1 : on hosts 1.2.3.2, 1.2.3.3.
- * Fragment 2 : on hosts 1.2.3.3, 1.2.3.1.
- * Fragment 3 : on hosts 1.2.3.1, 1.2.3.2.
- *
- * The expected distribution is as follows:
- * Host 1.2.3.1: fragments 0, 3.
- * Host 1.2.3.2: fragment 1.
- * Host 1.2.3.3: fragment 2.
- */
-void
-test__allocate_fragments_to_datanodes__4Fragments3Hosts2Replicates(void **state)
-{
- List* allDNProcessingLoads = NIL;
- List* data_fragment_list = NIL;
- List* blocks_list = NIL;
- ListCell* cell = NULL;
- DatanodeProcessingLoad* datanode_load = NULL;
- AllocatedDataFragment* allocated = NULL;
-
- data_fragment_list = build_data_fragments_list(4, 3, 2);
- assert_int_equal(4, list_length(data_fragment_list));
-
- allDNProcessingLoads = allocate_fragments_to_datanodes(data_fragment_list);
-
- assert_true(allDNProcessingLoads != NULL);
- assert_int_equal(3, list_length(allDNProcessingLoads));
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 0));
- blocks_list = build_blank_blocks_list(2);
- allocated = lfirst(list_nth_cell(blocks_list, 0));
- allocated->host = "1.2.3.1";
- allocated->index = 0;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 0";
- allocated->user_data = "user data 0";
- allocated = lfirst(list_nth_cell(blocks_list, 1));
- allocated->host = "1.2.3.1";
- allocated->index = 3;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 3";
- allocated->user_data = "user data 3";
- check_dn_load(datanode_load,
- "1.2.3.1", 0, blocks_list, 2, 3);
- list_free(blocks_list);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 1));
- blocks_list = build_blank_blocks_list(1);
- allocated = lfirst(list_nth_cell(blocks_list, 0));
- allocated->host = "1.2.3.2";
- allocated->index = 1;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 1";
- allocated->user_data = "user data 1";
- check_dn_load(datanode_load,
- "1.2.3.2", 0, blocks_list, 1, 3);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 2));
- allocated->host = "1.2.3.3";
- allocated->index = 2;
- allocated->fragment_md = "metadata 2";
- allocated->user_data = "user data 2";
- check_dn_load(datanode_load,
- "1.2.3.3", 0, blocks_list, 1, 2);
-
- /* cleanup */
- list_free(blocks_list);
- foreach (cell, allDNProcessingLoads)
- {
- DatanodeProcessingLoad* dn = (DatanodeProcessingLoad*)lfirst(cell);
- free_allocated_frags(dn->datanodeBlocks);
- }
- list_free(allDNProcessingLoads);
-}
-
-/*
- * Tests allocate_fragments_to_datanodes with 4 fragments over 3 hosts, with 1 replicates each,
- * so that they are distributed as follows:
- * Fragment 0 : on hosts 1.2.3.1.
- * Fragment 1 : on hosts 1.2.3.2.
- * Fragment 2 : on hosts 1.2.3.3.
- * Fragment 3 : on hosts 1.2.3.1.
- *
- * The expected distribution is as follows:
- * Host 1.2.3.1: fragments 0, 3.
- * Host 1.2.3.2: fragment 1.
- * Host 1.2.3.3: fragment 2.
- */
-void
-test__allocate_fragments_to_datanodes__4Fragments3Hosts1Replicates(void **state)
-{
- List* allDNProcessingLoads = NIL;
- List* data_fragment_list = NIL;
- List* blocks_list = NIL;
- ListCell* cell = NULL;
- DatanodeProcessingLoad* datanode_load = NULL;
- AllocatedDataFragment* allocated = NULL;
-
- data_fragment_list = build_data_fragments_list(4, 3, 1);
- assert_int_equal(4, list_length(data_fragment_list));
-
- allDNProcessingLoads = allocate_fragments_to_datanodes(data_fragment_list);
-
- assert_true(allDNProcessingLoads != NULL);
- assert_int_equal(3, list_length(allDNProcessingLoads));
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 0));
- blocks_list = build_blank_blocks_list(2);
- allocated = lfirst(list_nth_cell(blocks_list, 0));
- allocated->host = "1.2.3.1";
- allocated->index = 0;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 0";
- allocated->user_data = "user data 0";
- allocated = lfirst(list_nth_cell(blocks_list, 1));
- allocated->host = "1.2.3.1";
- allocated->index = 3;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 3";
- allocated->user_data = "user data 3";
- check_dn_load(datanode_load,
- "1.2.3.1", 0, blocks_list, 2, 2);
- list_free(blocks_list);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 1));
- blocks_list = build_blank_blocks_list(1);
- allocated = lfirst(list_nth_cell(blocks_list, 0));
- allocated->host = "1.2.3.2";
- allocated->index = 1;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 1";
- allocated->user_data = "user data 1";
- check_dn_load(datanode_load,
- "1.2.3.2", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 2));
- allocated->host = "1.2.3.3";
- allocated->index = 2;
- allocated->fragment_md = "metadata 2";
- allocated->user_data = "user data 2";
- check_dn_load(datanode_load,
- "1.2.3.3", 0, blocks_list, 1, 1);
-
- /* cleanup */
- list_free(blocks_list);
- foreach (cell, allDNProcessingLoads)
- {
- DatanodeProcessingLoad* dn = (DatanodeProcessingLoad*)lfirst(cell);
- free_allocated_frags(dn->datanodeBlocks);
- }
- list_free(allDNProcessingLoads);
-}
-
-/*
- * Tests allocate_fragments_to_datanodes with 7 fragments over 10 hosts, with 1 replicates each,
- * so that they are distributed as follows:
- * Fragment 0 : on hosts 1.2.3.1.
- * Fragment 1 : on hosts 1.2.3.2.
- * Fragment 2 : on hosts 1.2.3.3.
- * Fragment 3 : on hosts 1.2.3.4.
- * Fragment 4 : on hosts 1.2.3.5.
- * Fragment 5 : on hosts 1.2.3.6.
- * Fragment 6 : on hosts 1.2.3.7.
- *
- * The expected distribution is as follows:
- * Host 1.2.3.1: fragment 0.
- * Host 1.2.3.2: fragment 1.
- * Host 1.2.3.3: fragment 2.
- * Host 1.2.3.4: fragment 3.
- * Host 1.2.3.5: fragment 4.
- * Host 1.2.3.6: fragment 5.
- * Host 1.2.3.7: fragment 6.
- * Hosts 1.2.3.8, 1.2.3.9, 1.2.3.10: no fragments.
- */
-void
-test__allocate_fragments_to_datanodes__7Fragments10Hosts1Replicates(void **state)
-{
- List* allDNProcessingLoads = NIL;
- List* data_fragment_list = NIL;
- List* blocks_list = NIL;
- ListCell* cell = NULL;
- DatanodeProcessingLoad* datanode_load = NULL;
- AllocatedDataFragment* allocated = NULL;
-
- data_fragment_list = build_data_fragments_list(7, 10, 1);
- assert_int_equal(7, list_length(data_fragment_list));
-
- allDNProcessingLoads = allocate_fragments_to_datanodes(data_fragment_list);
-
- assert_true(allDNProcessingLoads != NULL);
- assert_int_equal(7, list_length(allDNProcessingLoads));
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 0));
- blocks_list = build_blank_blocks_list(1);
- allocated = lfirst(list_nth_cell(blocks_list, 0));
- allocated->host = "1.2.3.1";
- allocated->index = 0;
- allocated->rest_port = 0;
- allocated->source_name = "file.txt";
- allocated->fragment_md = "metadata 0";
- allocated->user_data = "user data 0";
- check_dn_load(datanode_load,
- "1.2.3.1", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 1));
- allocated->host = "1.2.3.2";
- allocated->index = 1;
- allocated->fragment_md = "metadata 1";
- allocated->user_data = "user data 1";
- check_dn_load(datanode_load,
- "1.2.3.2", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 2));
- allocated->host = "1.2.3.3";
- allocated->index = 2;
- allocated->fragment_md = "metadata 2";
- allocated->user_data = "user data 2";
- check_dn_load(datanode_load,
- "1.2.3.3", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 3));
- allocated->host = "1.2.3.4";
- allocated->index = 3;
- allocated->fragment_md = "metadata 3";
- allocated->user_data = "user data 3";
- check_dn_load(datanode_load,
- "1.2.3.4", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 4));
- allocated->host = "1.2.3.5";
- allocated->index = 4;
- allocated->fragment_md = "metadata 4";
- allocated->user_data = "user data 4";
- check_dn_load(datanode_load,
- "1.2.3.5", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 5));
- allocated->host = "1.2.3.6";
- allocated->index = 5;
- allocated->fragment_md = "metadata 5";
- allocated->user_data = "user data 5";
- check_dn_load(datanode_load,
- "1.2.3.6", 0, blocks_list, 1, 1);
-
- datanode_load = (DatanodeProcessingLoad*)lfirst(list_nth_cell(allDNProcessingLoads, 6));
- allocated->host = "1.2.3.7";
- allocated->index = 6;
- allocated->fragment_md = "metadata 6";
- allocated->user_data = "user data 6";
- check_dn_load(datanode_load,
- "1.2.3.7", 0, blocks_list, 1, 1);
-
- /* cleanup */
- list_free(blocks_list);
- foreach (cell, allDNProcessingLoads)
- {
- DatanodeProcessingLoad* dn = (DatanodeProcessingLoad*)lfirst(cell);
- free_allocated_frags(dn->datanodeBlocks);
- }
- list_free(allDNProcessingLoads);
-}