|
1 | 1 | import CoreMutation |
2 | 2 | @testable import PackageKit |
3 | 3 | import SwiftSyntax |
| 4 | +import SwiftSyntaxBuilder |
4 | 5 | import SyntaxMutation |
5 | 6 | import Testing |
6 | 7 |
|
7 | 8 | @Suite("SwiftSyntax Mutation") |
8 | 9 | struct SyntaxMutationTests { |
9 | 10 |
|
10 | | - @Test("empty") |
11 | | - func empty() { |
12 | | - let file = Source.File(name: "name", path: "path", code: "") |
13 | | - let mutants = Mutation.reverseString.mutants(for: file) |
14 | | - #expect(mutants.isEmpty) |
15 | | - } |
16 | | - |
17 | 11 | @Test("single") |
18 | 12 | func single() throws { |
19 | 13 |
|
20 | | - let file = Source.File(name: "name", path: "path", code: """ |
21 | | - func foo() { |
22 | | - print("hello!") |
23 | | - } |
24 | | - """) |
| 14 | + final class Visitor: MutationVisitor { |
25 | 15 |
|
26 | | - let mutants = Mutation.reverseString.mutants(for: file) |
27 | | - |
28 | | - try #require(mutants.count == 1) |
29 | | - #expect(mutants[0].original == file.code) |
30 | | - #expect(mutants[0].mutation == "Reverse String") |
31 | | - #expect(mutants[0].location.name == file.name) |
32 | | - #expect(mutants[0].location.path == file.path) |
33 | | - #expect(mutants[0].location.start == Source.Position(line: 2, column: 10, offset: 22)) |
34 | | - #expect(mutants[0].location.end == Source.Position(line: 2, column: 16, offset: 28)) |
35 | | - #expect(mutants[0].replacement == """ |
36 | | - func foo() { |
37 | | - print("!olleh") |
| 16 | + override func visit(_ node: CodeBlockItemListSyntax) -> SyntaxVisitorContinueKind { |
| 17 | + record(before: node, after: ExprSyntax(""" |
| 18 | + let name = "Daniel" |
| 19 | + """)) |
| 20 | + return super.visit(node) |
38 | 21 | } |
39 | | - """) |
40 | | - } |
41 | | - |
42 | | - @Test("multiple") |
43 | | - func multiple() throws { |
| 22 | + } |
44 | 23 |
|
45 | | - let file = Source.File(name: "name", path: "path", code: """ |
46 | | - func foo() { |
47 | | - print("hello!") |
48 | | - } |
49 | | - |
50 | | - var bar: String { "baz" } |
51 | | - """) |
| 24 | + let mutation = Mutation(name: "Replace File", visitor: Visitor.self) |
| 25 | + let file = Source.File(name: "name", path: "path", code: "") |
52 | 26 |
|
53 | | - let mutants = Mutation.reverseString.mutants(for: file) |
| 27 | + let mutants = mutation.mutants(for: file) |
54 | 28 |
|
55 | | - try #require(mutants.count == 2) |
| 29 | + try #require(mutants.count == 1) |
56 | 30 | #expect(mutants[0].original == file.code) |
57 | | - #expect(mutants[0].mutation == "Reverse String") |
| 31 | + #expect(mutants[0].mutation == mutation.name) |
58 | 32 | #expect(mutants[0].location.name == file.name) |
59 | 33 | #expect(mutants[0].location.path == file.path) |
60 | | - #expect(mutants[0].location.start == Source.Position(line: 2, column: 10, offset: 22)) |
61 | | - #expect(mutants[0].location.end == Source.Position(line: 2, column: 16, offset: 28)) |
| 34 | + #expect(mutants[0].location.start == Source.Position(line: 1, column: 1, offset: 0)) |
| 35 | + #expect(mutants[0].location.end == Source.Position(line: 1, column: 1, offset: 0)) |
62 | 36 | #expect(mutants[0].replacement == """ |
63 | | - func foo() { |
64 | | - print("!olleh") |
65 | | - } |
66 | | - |
67 | | - var bar: String { "baz" } |
68 | | - """) |
69 | | - |
70 | | - #expect(mutants[1].original == file.code) |
71 | | - #expect(mutants[1].mutation == "Reverse String") |
72 | | - #expect(mutants[1].location.name == file.name) |
73 | | - #expect(mutants[1].location.path == file.path) |
74 | | - #expect(mutants[1].location.start == Source.Position(line: 5, column: 20, offset: 53)) |
75 | | - #expect(mutants[1].location.end == Source.Position(line: 5, column: 23, offset: 56)) |
76 | | - #expect(mutants[1].replacement == """ |
77 | | - func foo() { |
78 | | - print("hello!") |
79 | | - } |
80 | | - |
81 | | - var bar: String { "zab" } |
| 37 | + let name = "Daniel" |
82 | 38 | """) |
83 | 39 | } |
84 | 40 | } |
85 | | - |
86 | | -extension Mutation { |
87 | | - |
88 | | - fileprivate static let reverseString = Mutation( |
89 | | - name: "Reverse String", |
90 | | - visitor: ReverseString.self, |
91 | | - ) |
92 | | -} |
93 | | - |
94 | | -final private class ReverseString: MutationVisitor { |
95 | | - |
96 | | - override func visit(_ node: StringLiteralExprSyntax) -> SyntaxVisitorContinueKind { |
97 | | - |
98 | | - for segment in node.segments { |
99 | | - switch segment { |
100 | | - case .expressionSegment: |
101 | | - continue |
102 | | - |
103 | | - case .stringSegment(let before): |
104 | | - let new = String(before.content.text.reversed()) |
105 | | - let after = StringSegmentSyntax(content: .stringSegment(new)) |
106 | | - record(before: before, after: after) |
107 | | - } |
108 | | - } |
109 | | - |
110 | | - return super.visit(node) |
111 | | - } |
112 | | -} |
0 commit comments