Path: blob/main/Tools/cases_generator/test_generator.py
12 views
# Sorry for using pytest, these tests are mostly just for me.1# Use pytest -vv for best results.23import tempfile45import generate_cases6from parser import StackEffect789def test_effect_sizes():10input_effects = [11x := StackEffect("x", "", "", ""),12y := StackEffect("y", "", "", "oparg"),13z := StackEffect("z", "", "", "oparg*2"),14]15output_effects = [16StackEffect("a", "", "", ""),17StackEffect("b", "", "", "oparg*4"),18StackEffect("c", "", "", ""),19]20other_effects = [21StackEffect("p", "", "", "oparg<<1"),22StackEffect("q", "", "", ""),23StackEffect("r", "", "", ""),24]25assert generate_cases.effect_size(x) == (1, "")26assert generate_cases.effect_size(y) == (0, "oparg")27assert generate_cases.effect_size(z) == (0, "oparg*2")2829assert generate_cases.list_effect_size(input_effects) == (1, "oparg + oparg*2")30assert generate_cases.list_effect_size(output_effects) == (2, "oparg*4")31assert generate_cases.list_effect_size(other_effects) == (2, "(oparg<<1)")3233assert generate_cases.string_effect_size(generate_cases.list_effect_size(input_effects)) == "1 + oparg + oparg*2"34assert generate_cases.string_effect_size(generate_cases.list_effect_size(output_effects)) == "2 + oparg*4"35assert generate_cases.string_effect_size(generate_cases.list_effect_size(other_effects)) == "2 + (oparg<<1)"363738def run_cases_test(input: str, expected: str):39temp_input = tempfile.NamedTemporaryFile("w+")40temp_input.write(generate_cases.BEGIN_MARKER)41temp_input.write(input)42temp_input.write(generate_cases.END_MARKER)43temp_input.flush()44temp_output = tempfile.NamedTemporaryFile("w+")45temp_metadata = tempfile.NamedTemporaryFile("w+")46temp_pymetadata = tempfile.NamedTemporaryFile("w+")47temp_executor = tempfile.NamedTemporaryFile("w+")48a = generate_cases.Analyzer(49[temp_input.name],50temp_output.name,51temp_metadata.name,52temp_pymetadata.name,53temp_executor.name,54)55a.parse()56a.analyze()57if a.errors:58raise RuntimeError(f"Found {a.errors} errors")59a.write_instructions()60temp_output.seek(0)61lines = temp_output.readlines()62while lines and lines[0].startswith("// "):63lines.pop(0)64actual = "".join(lines)65# if actual.rstrip() != expected.rstrip():66# print("Actual:")67# print(actual)68# print("Expected:")69# print(expected)70# print("End")71assert actual.rstrip() == expected.rstrip()7273def test_inst_no_args():74input = """75inst(OP, (--)) {76spam();77}78"""79output = """80TARGET(OP) {81spam();82DISPATCH();83}84"""85run_cases_test(input, output)8687def test_inst_one_pop():88input = """89inst(OP, (value --)) {90spam();91}92"""93output = """94TARGET(OP) {95PyObject *value = stack_pointer[-1];96spam();97STACK_SHRINK(1);98DISPATCH();99}100"""101run_cases_test(input, output)102103def test_inst_one_push():104input = """105inst(OP, (-- res)) {106spam();107}108"""109output = """110TARGET(OP) {111PyObject *res;112spam();113STACK_GROW(1);114stack_pointer[-1] = res;115DISPATCH();116}117"""118run_cases_test(input, output)119120def test_inst_one_push_one_pop():121input = """122inst(OP, (value -- res)) {123spam();124}125"""126output = """127TARGET(OP) {128PyObject *value = stack_pointer[-1];129PyObject *res;130spam();131stack_pointer[-1] = res;132DISPATCH();133}134"""135run_cases_test(input, output)136137def test_binary_op():138input = """139inst(OP, (left, right -- res)) {140spam();141}142"""143output = """144TARGET(OP) {145PyObject *right = stack_pointer[-1];146PyObject *left = stack_pointer[-2];147PyObject *res;148spam();149STACK_SHRINK(1);150stack_pointer[-1] = res;151DISPATCH();152}153"""154run_cases_test(input, output)155156def test_overlap():157input = """158inst(OP, (left, right -- left, result)) {159spam();160}161"""162output = """163TARGET(OP) {164PyObject *right = stack_pointer[-1];165PyObject *left = stack_pointer[-2];166PyObject *result;167spam();168stack_pointer[-1] = result;169DISPATCH();170}171"""172run_cases_test(input, output)173174def test_predictions_and_eval_breaker():175input = """176inst(OP1, (--)) {177}178inst(OP3, (arg -- res)) {179DEOPT_IF(xxx, OP1);180CHECK_EVAL_BREAKER();181}182"""183output = """184TARGET(OP1) {185PREDICTED(OP1);186DISPATCH();187}188189TARGET(OP3) {190PyObject *arg = stack_pointer[-1];191PyObject *res;192DEOPT_IF(xxx, OP1);193stack_pointer[-1] = res;194CHECK_EVAL_BREAKER();195DISPATCH();196}197"""198run_cases_test(input, output)199200def test_error_if_plain():201input = """202inst(OP, (--)) {203ERROR_IF(cond, label);204}205"""206output = """207TARGET(OP) {208if (cond) goto label;209DISPATCH();210}211"""212run_cases_test(input, output)213214def test_error_if_plain_with_comment():215input = """216inst(OP, (--)) {217ERROR_IF(cond, label); // Comment is ok218}219"""220output = """221TARGET(OP) {222if (cond) goto label;223DISPATCH();224}225"""226run_cases_test(input, output)227228def test_error_if_pop():229input = """230inst(OP, (left, right -- res)) {231ERROR_IF(cond, label);232}233"""234output = """235TARGET(OP) {236PyObject *right = stack_pointer[-1];237PyObject *left = stack_pointer[-2];238PyObject *res;239if (cond) goto pop_2_label;240STACK_SHRINK(1);241stack_pointer[-1] = res;242DISPATCH();243}244"""245run_cases_test(input, output)246247def test_cache_effect():248input = """249inst(OP, (counter/1, extra/2, value --)) {250}251"""252output = """253TARGET(OP) {254PyObject *value = stack_pointer[-1];255uint16_t counter = read_u16(&next_instr[0].cache);256uint32_t extra = read_u32(&next_instr[1].cache);257STACK_SHRINK(1);258next_instr += 3;259DISPATCH();260}261"""262run_cases_test(input, output)263264def test_suppress_dispatch():265input = """266inst(OP, (--)) {267goto somewhere;268}269"""270output = """271TARGET(OP) {272goto somewhere;273}274"""275run_cases_test(input, output)276277def test_macro_instruction():278input = """279inst(OP1, (counter/1, left, right -- left, right)) {280op1(left, right);281}282op(OP2, (extra/2, arg2, left, right -- res)) {283res = op2(arg2, left, right);284}285macro(OP) = OP1 + cache/2 + OP2;286inst(OP3, (unused/5, arg2, left, right -- res)) {287res = op3(arg2, left, right);288}289family(op, INLINE_CACHE_ENTRIES_OP) = { OP, OP3 };290"""291output = """292TARGET(OP1) {293PyObject *right = stack_pointer[-1];294PyObject *left = stack_pointer[-2];295uint16_t counter = read_u16(&next_instr[0].cache);296op1(left, right);297next_instr += 1;298DISPATCH();299}300301TARGET(OP) {302PyObject *_tmp_1 = stack_pointer[-1];303PyObject *_tmp_2 = stack_pointer[-2];304PyObject *_tmp_3 = stack_pointer[-3];305{306PyObject *right = _tmp_1;307PyObject *left = _tmp_2;308uint16_t counter = read_u16(&next_instr[0].cache);309op1(left, right);310_tmp_2 = left;311_tmp_1 = right;312}313{314PyObject *right = _tmp_1;315PyObject *left = _tmp_2;316PyObject *arg2 = _tmp_3;317PyObject *res;318uint32_t extra = read_u32(&next_instr[3].cache);319res = op2(arg2, left, right);320_tmp_3 = res;321}322next_instr += 5;323static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");324STACK_SHRINK(2);325stack_pointer[-1] = _tmp_3;326DISPATCH();327}328329TARGET(OP3) {330PyObject *right = stack_pointer[-1];331PyObject *left = stack_pointer[-2];332PyObject *arg2 = stack_pointer[-3];333PyObject *res;334res = op3(arg2, left, right);335STACK_SHRINK(2);336stack_pointer[-1] = res;337next_instr += 5;338DISPATCH();339}340"""341run_cases_test(input, output)342343def test_array_input():344input = """345inst(OP, (below, values[oparg*2], above --)) {346spam();347}348"""349output = """350TARGET(OP) {351PyObject *above = stack_pointer[-1];352PyObject **values = (stack_pointer - (1 + oparg*2));353PyObject *below = stack_pointer[-(2 + oparg*2)];354spam();355STACK_SHRINK(oparg*2);356STACK_SHRINK(2);357DISPATCH();358}359"""360run_cases_test(input, output)361362def test_array_output():363input = """364inst(OP, (unused, unused -- below, values[oparg*3], above)) {365spam(values, oparg);366}367"""368output = """369TARGET(OP) {370PyObject *below;371PyObject **values = stack_pointer - (2) + 1;372PyObject *above;373spam(values, oparg);374STACK_GROW(oparg*3);375stack_pointer[-1] = above;376stack_pointer[-(2 + oparg*3)] = below;377DISPATCH();378}379"""380run_cases_test(input, output)381382def test_array_input_output():383input = """384inst(OP, (values[oparg] -- values[oparg], above)) {385spam(values, oparg);386}387"""388output = """389TARGET(OP) {390PyObject **values = (stack_pointer - oparg);391PyObject *above;392spam(values, oparg);393STACK_GROW(1);394stack_pointer[-1] = above;395DISPATCH();396}397"""398run_cases_test(input, output)399400def test_array_error_if():401input = """402inst(OP, (extra, values[oparg] --)) {403ERROR_IF(oparg == 0, somewhere);404}405"""406output = """407TARGET(OP) {408PyObject **values = (stack_pointer - oparg);409PyObject *extra = stack_pointer[-(1 + oparg)];410if (oparg == 0) { STACK_SHRINK(oparg); goto pop_1_somewhere; }411STACK_SHRINK(oparg);412STACK_SHRINK(1);413DISPATCH();414}415"""416run_cases_test(input, output)417418def test_cond_effect():419input = """420inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {421output = spam(oparg, input);422}423"""424output = """425TARGET(OP) {426PyObject *cc = stack_pointer[-1];427PyObject *input = ((oparg & 1) == 1) ? stack_pointer[-(1 + (((oparg & 1) == 1) ? 1 : 0))] : NULL;428PyObject *aa = stack_pointer[-(2 + (((oparg & 1) == 1) ? 1 : 0))];429PyObject *xx;430PyObject *output = NULL;431PyObject *zz;432output = spam(oparg, input);433STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0));434STACK_GROW(((oparg & 2) ? 1 : 0));435stack_pointer[-1] = zz;436if (oparg & 2) { stack_pointer[-(1 + ((oparg & 2) ? 1 : 0))] = output; }437stack_pointer[-(2 + ((oparg & 2) ? 1 : 0))] = xx;438DISPATCH();439}440"""441run_cases_test(input, output)442443def test_macro_cond_effect():444input = """445op(A, (left, middle, right --)) {446# Body of A447}448op(B, (-- deep, extra if (oparg), res)) {449# Body of B450}451macro(M) = A + B;452"""453output = """454TARGET(M) {455PyObject *_tmp_1 = stack_pointer[-1];456PyObject *_tmp_2 = stack_pointer[-2];457PyObject *_tmp_3 = stack_pointer[-3];458{459PyObject *right = _tmp_1;460PyObject *middle = _tmp_2;461PyObject *left = _tmp_3;462# Body of A463}464{465PyObject *deep;466PyObject *extra = NULL;467PyObject *res;468# Body of B469_tmp_3 = deep;470if (oparg) { _tmp_2 = extra; }471_tmp_1 = res;472}473STACK_SHRINK(1);474STACK_GROW((oparg ? 1 : 0));475stack_pointer[-1] = _tmp_1;476if (oparg) { stack_pointer[-2] = _tmp_2; }477stack_pointer[-3] = _tmp_3;478DISPATCH();479}480"""481run_cases_test(input, output)482483484