#include #include #include #include #include #include "resreq.h" #include "utils.h" void test_parse_section1(void) { char* resreq = "type == any"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data; rc = parse_section(&data, (char*)resreq, &errmsg); TEST_ASSERT_TRUE(rc >= 0); TEST_ASSERT_TRUE(data.selectString != NULL); TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString == NULL) && (data.sameString == NULL) && (data.affinityString == NULL)); TEST_ASSERT_TRUE(errmsg == NULL); printf("select: %s\n", data.selectString); FREEUP(data.selectString); } void test_parse_section2(void) { char* resreq = "select[type == any]"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data; rc = parse_section(&data, (char*)resreq, &errmsg); TEST_ASSERT_TRUE(rc >= 0); TEST_ASSERT_TRUE(data.selectString != NULL); TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString == NULL) && (data.sameString == NULL) && (data.affinityString == NULL)); TEST_ASSERT_TRUE(errmsg == NULL); printf("select: %s\n", data.selectString); FREEUP(data.selectString); } void test_parse_section_fail(void) { char* resreq = "select[type == any] rusage[mem=20:lic=55] span[ptile=1] " "same[type] same[abcd] affinity[core(20)]"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data = {0}; rc = parse_section(&data, (char*)resreq, &errmsg); TEST_ASSERT_TRUE(rc < 0); TEST_ASSERT_TRUE(data.selectString == NULL); TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString == NULL) && (data.sameString == NULL) && (data.affinityString == NULL)); TEST_ASSERT_TRUE(errmsg != NULL); printf("Parse Error:\n%s\n", errmsg); FREEUP(errmsg); } void test_parse_section3(void) { char* resreq = "type == any span[ptile=1]"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data; rc = parse_section(&data, (char*)resreq, &errmsg); if (rc < 0) { if (errmsg != NULL) { printf("%s", errmsg); FREEUP(errmsg); } } TEST_ASSERT_TRUE(rc >= 0); TEST_ASSERT_TRUE(data.selectString != NULL); TEST_ASSERT_TRUE((data.rusageString == NULL) && (data.spanString != NULL) && (data.sameString == NULL) && (data.affinityString == NULL)); TEST_ASSERT_TRUE(errmsg == NULL); printf("select: %s\n", data.selectString); printf("span: %s\n", data.spanString); FREEUP(data.selectString); FREEUP(data.spanString); } void test_parse_rusage1(void) { char* rusageString = "mem=20:duration=300:decay=1,lic=55:duration=20m:decay=0"; char* errmsg = NULL; int rc = 0; xlist_t rusages; xlist_init(&rusages, 8); rc = parse_rusage(&rusages, rusageString, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { int i; for (i = 0; i < rusages.count; i++) { rusage_value_t* v = (rusage_value_t*)xlist_get(&rusages, i); TEST_ASSERT_TRUE(v != NULL); switch (i) { case 0: TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_DEFAULT); TEST_ASSERT_TRUE(v->decay_flag == 1); break; case 1: TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_DEFAULT); TEST_ASSERT_TRUE(v->decay_flag == 0); break; default: break; } printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, v->duration, v->decay_flag); kill_rusage_value(v); free(v); } xlist_fini(&rusages); } } void test_parse_rusage2(void) { char* rusageString = "mem=20/host:duration=300:decay=1,lic=55/job:duration=20m:decay=0"; char* errmsg = NULL; int rc = 0; xlist_t rusages; xlist_init(&rusages, 8); rc = parse_rusage(&rusages, rusageString, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { int i; for (i = 0; i < rusages.count; i++) { rusage_value_t* v = (rusage_value_t*)xlist_get(&rusages, i); TEST_ASSERT_TRUE(v != NULL); switch (i) { case 0: TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_HOST); TEST_ASSERT_TRUE(v->decay_flag == 1); break; case 1: TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_JOB); TEST_ASSERT_TRUE(v->decay_flag == 0); break; default: break; } printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, v->duration, v->decay_flag); kill_rusage_value(v); free(v); } xlist_fini(&rusages); } } void test_resreq_primary(void) { char* resreqString = "select[type==any] " "rusage[mem=20:duration=300:decay=1,lic=55:duration=20m:decay=0]"; char* errmsg = NULL; int rc = 0; xce_primary_resreq_t resreq; rc = parse_resreq_primary(&resreq, resreqString, NULL, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { int i; xlist_t* rusages = &(resreq.rusages); for (i = 0; i < rusages->count; i++) { rusage_value_t* v = (rusage_value_t*)xlist_get(rusages, i); TEST_ASSERT_TRUE(v != NULL); switch (i) { case 0: TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_DEFAULT); TEST_ASSERT_TRUE(v->decay_flag == 1); break; case 1: TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_DEFAULT); TEST_ASSERT_TRUE(v->decay_flag == 0); break; default: break; } printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, v->duration, v->decay_flag); kill_rusage_value(v); free(v); } xlist_fini(rusages); } } void test_resreq_primary2(void) { char* resreqString = "select[type==any] "; char* errmsg = NULL; int rc = 0; xce_primary_resreq_t resreq; rc = parse_resreq_primary(&resreq, resreqString, NULL, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { int i; xlist_t* rusages = &(resreq.rusages); TEST_ASSERT_TRUE(rusages->count == 0); xlist_fini(rusages); } } void test_resreq1(void) { char* resreqString = "select[type==any] " "rusage[mem=20:duration=300:decay=1,lic=55:duration=20m:decay=0]"; char* errmsg = NULL; int rc = 0; xce_resreq_t resreq; rc = parse_resreq(&resreq, resreqString, NULL, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { int i; xlist_t* rusages = NULL; char* buf = NULL; TEST_ASSERT_TRUE(resreq.tag == XCE_RESREQ_PRIMARY); rusages = &(resreq.u.primary->rusages); for (i = 0; i < rusages->count; i++) { rusage_value_t* v = (rusage_value_t*)xlist_get(rusages, i); TEST_ASSERT_TRUE(v != NULL); switch (i) { case 0: TEST_ASSERT_TRUE(strcmp(v->res, "mem") == 0); TEST_ASSERT_TRUE(fabs(v->value - 20.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 18000) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_DEFAULT); TEST_ASSERT_TRUE(v->decay_flag == 1); break; case 1: TEST_ASSERT_TRUE(strcmp(v->res, "lic") == 0); TEST_ASSERT_TRUE(fabs(v->value - 55.0) < 0.001); TEST_ASSERT_TRUE(fabs(v->duration - 1200) < 0.001); TEST_ASSERT_TRUE(v->per_flag == PER_DEFAULT); TEST_ASSERT_TRUE(v->decay_flag == 0); break; default: break; } printf("rusage: %s %f %d %f %d\n", v->res, v->value, v->per_flag, v->duration, v->decay_flag); } rc = format_resreq(&buf, &resreq); if (rc >= 0) { printf("%s\n", buf); } FREEUP(buf); kill_resreq(&resreq); } } void test_resreq2(void) { char* resreqString = "2*{rusage[mem=100:duration=20:decay=1]} + " "4*{rusage[mem=80:duration=30:decay=1]}"; char* errmsg = NULL; int rc = 0; xce_resreq_t resreq; memset(&resreq, 0x0, sizeof(resreq)); rc = parse_resreq(&resreq, resreqString, NULL, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { char* buf = NULL; TEST_ASSERT_TRUE(resreq.tag == XCE_RESREQ_COMPOUND); rc = format_resreq(&buf, &resreq); if (rc >= 0) { printf("%s\n", buf); } FREEUP(buf); kill_resreq(&resreq); } } void test_resreq3(void) { char* resreqString = "{2*{rusage[mem=100:duration=20:decay=1]} + " "4*{rusage[mem=80:duration=30:decay=1]}} || " "{3*{rusage[mem=150:duration=15:decay=1]} + " "6*{rusage[mem=120:duration=20:decay=1]}} "; char* errmsg = NULL; int rc = 0; xce_resreq_t resreq; memset(&resreq, 0x0, sizeof(resreq)); rc = parse_resreq(&resreq, resreqString, NULL, &errmsg); TEST_ASSERT_TRUE(rc >= 0); if (rc >= 0) { char* buf = NULL; TEST_ASSERT_TRUE(resreq.tag == XCE_RESREQ_ALTER); rc = format_resreq(&buf, &resreq); if (rc >= 0) { printf("%s\n", buf); } if (buf != NULL) { free(buf); } kill_resreq(&resreq); } } /* * Boundary tests for the P0-2 span-bleed fix in section.peg. * * Before the fix line 50 read: !("span[]" / "]") * After the fix line 50 reads: !("span[" / "]") * * With the old grammar the negative lookahead would only suppress * consumption of the literal token "span[]", so any span clause * with content (e.g. "span[ptile=1]") was silently absorbed into * selectString. These tests verify the corrected boundary. */ /* Test 1: explicit select[...] with a non-empty span[...] clause. */ void test_parse_section_explicit_select_with_span(void) { char* resreq = "select[type==linux] span[ptile=1]"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data = {0}; rc = parse_section(&data, (char*)resreq, &errmsg); TEST_ASSERT_TRUE(rc >= 0); printf("select: %s\n", data.selectString ? data.selectString : "(null)"); printf("span: %s\n", data.spanString ? data.spanString : "(null)"); /* select must contain the predicate, not bleed into the span keyword */ TEST_ASSERT_TRUE(data.selectString != NULL); TEST_ASSERT_TRUE(strstr(data.selectString, "type==linux") != NULL); /* span must be parsed separately and hold only its content */ TEST_ASSERT_TRUE(data.spanString != NULL); TEST_ASSERT_TRUE(strstr(data.spanString, "ptile=1") != NULL); /* unrelated clauses must be absent */ TEST_ASSERT_TRUE(data.rusageString == NULL); TEST_ASSERT_TRUE(data.sameString == NULL); TEST_ASSERT_TRUE(data.affinityString == NULL); FREEUP(data.selectString); FREEUP(data.spanString); FREEUP(errmsg); } /* Test 2: all three major clauses — select, rusage, span — in one string. */ void test_parse_section_explicit_select_rusage_span(void) { char* resreq = "select[a&&b] rusage[mem=100] span[ptile=2]"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data = {0}; rc = parse_section(&data, (char*)resreq, &errmsg); TEST_ASSERT_TRUE(rc >= 0); printf("select: %s\n", data.selectString ? data.selectString : "(null)"); printf("rusage: %s\n", data.rusageString ? data.rusageString : "(null)"); printf("span: %s\n", data.spanString ? data.spanString : "(null)"); TEST_ASSERT_TRUE(data.selectString != NULL); TEST_ASSERT_TRUE(strstr(data.selectString, "a&&b") != NULL); TEST_ASSERT_TRUE(data.rusageString != NULL); TEST_ASSERT_TRUE(strstr(data.rusageString, "mem=100") != NULL); TEST_ASSERT_TRUE(data.spanString != NULL); TEST_ASSERT_TRUE(strstr(data.spanString, "ptile=2") != NULL); FREEUP(data.selectString); FREEUP(data.rusageString); FREEUP(data.spanString); FREEUP(errmsg); } /* * Test 3: the core regression guard — selectString must NOT contain the * substring "span" when a span clause is present. With the old buggy * grammar the span clause text would bleed into selectString. */ void test_parse_section_span_not_in_select(void) { char* resreq = "select[gpu] span[ptile=4]"; char* errmsg = NULL; int rc = 0; xce_resreq_data_t data = {0}; rc = parse_section(&data, (char*)resreq, &errmsg); TEST_ASSERT_TRUE(rc >= 0); printf("select: %s\n", data.selectString ? data.selectString : "(null)"); printf("span: %s\n", data.spanString ? data.spanString : "(null)"); /* selectString must not contain the span keyword (bleed check) */ TEST_ASSERT_TRUE(data.selectString != NULL); TEST_ASSERT_TRUE(strstr(data.selectString, "span") == NULL); /* span content must be correctly isolated */ TEST_ASSERT_TRUE(data.spanString != NULL); TEST_ASSERT_TRUE(strstr(data.spanString, "ptile=4") != NULL); FREEUP(data.selectString); FREEUP(data.spanString); FREEUP(errmsg); } void test_resreq(void) { printf("\n>> resreq test\n\n"); RUN_TEST(test_parse_section1); RUN_TEST(test_parse_section2); RUN_TEST(test_parse_section_fail); RUN_TEST(test_parse_section3); RUN_TEST(test_parse_rusage1); RUN_TEST(test_parse_rusage2); RUN_TEST(test_resreq_primary); RUN_TEST(test_resreq_primary2); RUN_TEST(test_resreq1); RUN_TEST(test_resreq2); RUN_TEST(test_resreq3); RUN_TEST(test_parse_section_explicit_select_with_span); RUN_TEST(test_parse_section_explicit_select_rusage_span); RUN_TEST(test_parse_section_span_not_in_select); }