review

review patchsets using your default editor
Log | Files | Refs

reviewer_test.odin (4453B)


      1 package reviewer
      2 
      3 import "core:strings"
      4 import "core:testing"
      5 
      6 import "../change"
      7 import "../job"
      8 import "../provider"
      9 
     10 // echoing is a provider that answers every ask with the text given.
     11 echoing :: proc(text: string) -> provider.Provider {
     12 	argv := make([]string, 2, context.temp_allocator)
     13 	argv[0], argv[1] = "echo", text
     14 	return provider.Provider{kind = .Command, argv = argv}
     15 }
     16 
     17 with_tests :: proc() -> change.Change {
     18 	c := change.Change{}
     19 	c.tests = make([dynamic]change.Function, context.temp_allocator)
     20 	append(
     21 		&c.tests,
     22 		change.Function {
     23 			name = "TestX",
     24 			file = "x_test.go",
     25 			line = 4,
     26 			body = "func TestX(t *testing.T) {}",
     27 		},
     28 	)
     29 	return c
     30 }
     31 
     32 @(test)
     33 findings_are_read_and_jobs_without_a_subject_are_skipped :: proc(t: ^testing.T) {
     34 	context.allocator = context.temp_allocator
     35 	p := echoing(
     36 		`{"findings":[{"rule":"cannot-fail","severity":"must-fix","file":"x_test.go","line":4,"symbol":"TestX","message":"asserts nothing","fix":"assert"},{"rule":"invented","severity":"note","message":"x","fix":"y"}]}`,
     37 	)
     38 	r := Reviewer {
     39 		provider = p,
     40 		name     = provider.name(p),
     41 		verify   = false,
     42 	}
     43 	c := with_tests()
     44 	result := run(&r, &c, job.all(), serial = true)
     45 	testing.expect_value(t, len(result.failures), 0)
     46 	testing.expect_value(t, len(result.findings), 1)
     47 	if len(result.findings) == 1 {
     48 		f := result.findings[0]
     49 		testing.expect_value(t, f.job, "tests")
     50 		testing.expect_value(t, f.rule, "cannot-fail")
     51 		testing.expect_value(t, f.line, 4)
     52 		testing.expect(t, !f.verified)
     53 	}
     54 	testing.expect_value(
     55 		t,
     56 		strings.join(result.skipped[:], ",", context.temp_allocator),
     57 		"duplication,namer,claims,hygiene",
     58 	)
     59 }
     60 
     61 @(test)
     62 a_second_reading_retracts_what_it_does_not_hold :: proc(t: ^testing.T) {
     63 	context.allocator = context.temp_allocator
     64 	// One answer that is both a findings object and a verdicts object:
     65 	// the first reading reports one finding, the second says it falls.
     66 	p := echoing(
     67 		`{"findings":[{"rule":"cannot-fail","severity":"must-fix","file":"x_test.go","line":4,"symbol":"TestX","message":"m","fix":"f"}],"verdicts":[{"index":0,"holds":false,"reason":"the test can fail"}]}`,
     68 	)
     69 	r := Reviewer {
     70 		provider = p,
     71 		name     = provider.name(p),
     72 		verify   = true,
     73 	}
     74 	c := with_tests()
     75 	result := run(&r, &c, job.all(), serial = true)
     76 	testing.expect_value(t, len(result.failures), 0)
     77 	testing.expect_value(t, len(result.findings), 0)
     78 	testing.expect_value(t, len(result.retracted), 1)
     79 	if len(result.retracted) == 1 {
     80 		testing.expect_value(t, result.retracted[0].reason, "the test can fail")
     81 		testing.expect_value(t, result.retracted[0].finding.rule, "cannot-fail")
     82 	}
     83 	// A verdict that holds leaves the finding standing, verified.
     84 	holds := echoing(
     85 		`{"findings":[{"rule":"cannot-fail","severity":"must-fix","file":"x_test.go","line":4,"symbol":"TestX","message":"m","fix":"f"}],"verdicts":[{"index":0,"holds":true,"reason":"it stands"}]}`,
     86 	)
     87 	r = Reviewer {
     88 		provider = holds,
     89 		name     = provider.name(holds),
     90 		verify   = true,
     91 	}
     92 	c = with_tests()
     93 	result = run(&r, &c, job.all(), serial = true)
     94 	testing.expect_value(t, len(result.findings), 1)
     95 	if len(result.findings) == 1 {
     96 		testing.expect(t, result.findings[0].verified)
     97 	}
     98 }
     99 
    100 @(test)
    101 a_verdict_that_cannot_be_asked_fails_open :: proc(t: ^testing.T) {
    102 	context.allocator = context.temp_allocator
    103 	// The answer is findings only, so the verdict ask reads no verdicts
    104 	// twice over: the findings stand unverified and the failure is named.
    105 	p := echoing(
    106 		`{"findings":[{"rule":"cannot-fail","severity":"must-fix","file":"x_test.go","line":4,"symbol":"TestX","message":"m","fix":"f"}]}`,
    107 	)
    108 	r := Reviewer {
    109 		provider = p,
    110 		name     = provider.name(p),
    111 		verify   = true,
    112 	}
    113 	c := with_tests()
    114 	result := run(&r, &c, job.all(), serial = true)
    115 	testing.expect_value(t, len(result.findings), 1)
    116 	if len(result.findings) == 1 {
    117 		testing.expect(t, result.findings[0].verified)
    118 	}
    119 	testing.expectf(
    120 		t,
    121 		len(result.failures) == 0,
    122 		"an omitted verdict stands rather than falls: %v",
    123 		result.failures,
    124 	)
    125 	prose := echoing("I have nothing to say")
    126 	r = Reviewer {
    127 		provider = prose,
    128 		name     = provider.name(prose),
    129 		verify   = false,
    130 	}
    131 	c = with_tests()
    132 	result = run(&r, &c, job.all(), serial = true)
    133 	testing.expect_value(t, len(result.failures), 1)
    134 	if len(result.failures) == 1 {
    135 		testing.expect(
    136 			t,
    137 			strings.has_prefix(
    138 				result.failures[0],
    139 				"tests: no findings object in the answer, twice",
    140 			),
    141 		)
    142 	}
    143 }