DiffTest   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 254
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 254
rs 10
c 3
b 0
f 0
wmc 25

19 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 3 1
A test_add_lines() 0 4 1
A test_double_addition() 0 7 1
A test_equality() 0 19 1
A test_delete_line() 0 6 1
A test_json_export() 0 8 1
A test_addition_rename() 0 13 1
A test_stats() 0 7 1
A test_double_changes_with_same_diff() 0 8 2
A test_rename() 0 7 3
A test_delete() 0 12 2
B test_from_string_arrays() 0 25 1
A test_modified() 0 23 1
A test_from_clang_fixit() 0 18 3
B test_affected_code() 0 26 1
A test_addition() 0 20 1
A test_delete_lines() 0 6 1
A test_change_line() 0 10 1
A test_len() 0 7 1
1
import json
2
import unittest
3
from unittest.case import SkipTest
4
5
from coalib.output.JSONEncoder import create_json_encoder
6
from coalib.results.Diff import ConflictError, Diff, SourceRange
7
8
9
class DiffTest(unittest.TestCase):
10
11
    def setUp(self):
12
        self.file = ["1", "2", "3", "4"]
13
        self.uut = Diff(self.file)
14
15
    def test_add_lines(self):
16
        self.uut.add_lines(0, [])
17
        self.uut.add_lines(0, ["t"])
18
        self.uut.add_lines(0, [])
19
20
    def test_double_addition(self):
21
        self.uut.add_lines(0, ["t"])
22
23
        # No double addition allowed
24
        self.assertRaises(ConflictError, self.uut.add_lines, 0, ["t"])
25
        self.assertRaises(ValueError, self.uut.add_lines, -1, ["t"])
26
        self.assertRaises(TypeError, self.uut.add_lines, "str", ["t"])
27
28
    def test_delete_line(self):
29
        self.uut.delete_line(1)
30
        self.uut.delete_line(1)  # Double deletion possible without conflict
31
        additions, deletions = self.uut.stats()
32
        self.assertEqual(deletions, 1)
33
        self.assertRaises(ValueError, self.uut.delete_line, 0)
34
35
    def test_delete_lines(self):
36
        self.uut.delete_lines(1, 10)
37
        self.uut.delete_lines(10, 20)
38
        additions, deletions = self.uut.stats()
39
        self.assertEqual(deletions, 20)
40
        self.assertRaises(ValueError, self.uut.delete_lines, 0, 10)
41
42
    def test_change_line(self):
43
        self.assertEqual(len(self.uut), 0)
44
        self.uut.change_line(2, "1", "2")
45
        self.assertEqual(len(self.uut), 2)
46
        self.assertRaises(ConflictError, self.uut.change_line, 2, "1", "3")
47
        self.assertRaises(ValueError, self.uut.change_line, 0, "1", "2")
48
49
        self.uut.delete_line(1)
50
        # Line was deleted, unchangeable
51
        self.assertRaises(ConflictError, self.uut.change_line, 1, "1", "2")
52
53
    def test_double_changes_with_same_diff(self):
54
        self.uut.change_line(2, "1", "2")
55
56
        # Double addition when diff is equal is allowed
57
        try:
58
            self.uut.change_line(2, "1", "2")
59
        except Exception:
60
            self.fail('We should not have a conflict on same diff!')
61
62
    def test_affected_code(self):
63
        self.assertEqual(self.uut.affected_code("file"), [])
64
65
        self.uut.add_lines(0, ["test"])
66
        affected_code = [
67
            SourceRange.from_values("file", start_line=1)]
68
        self.assertEqual(self.uut.affected_code("file"), affected_code)
69
70
        self.uut.delete_line(2)
71
        affected_code = [
72
            SourceRange.from_values("file", start_line=1),
73
            SourceRange.from_values("file", start_line=2)]
74
        self.assertEqual(self.uut.affected_code("file"), affected_code)
75
76
        self.uut.delete_line(3)
77
        affected_code = [
78
            SourceRange.from_values("file", start_line=1),
79
            SourceRange.from_values("file", start_line=2, end_line=3)]
80
        self.assertEqual(self.uut.affected_code("file"), affected_code)
81
82
        self.uut.delete_line(6)
83
        affected_code = [
84
            SourceRange.from_values("file", start_line=1),
85
            SourceRange.from_values("file", start_line=2, end_line=3),
86
            SourceRange.from_values('file', start_line=6)]
87
        self.assertEqual(self.uut.affected_code("file"), affected_code)
88
89
    def test_len(self):
90
        self.uut.delete_line(2)
91
        self.assertEqual(len(self.uut), 1)
92
        self.uut.add_lines(2, ["2.3", "2.5", "2.6"])
93
        self.assertEqual(len(self.uut), 4)
94
        self.uut.change_line(1, "1", "1.1")
95
        self.assertEqual(len(self.uut), 6)
96
97
    def test_stats(self):
98
        self.uut.delete_line(2)
99
        self.assertEqual(self.uut.stats(), (0, 1))
100
        self.uut.add_lines(2, ["2.3", "2.5", "2.6"])
101
        self.assertEqual(self.uut.stats(), (3, 1))
102
        self.uut.change_line(1, "1", "1.1")
103
        self.assertEqual(self.uut.stats(), (4, 2))
104
105
    def test_modified(self):
106
        result_file = ["0.1",
107
                       "0.2",
108
                       "1",
109
                       "1.1",
110
                       "3.changed",
111
                       "4"]
112
113
        self.uut.delete_line(2)
114
        self.uut.add_lines(0, ["0.1", "0.2"])
115
        self.uut.add_lines(1, ["1.1"])
116
        self.uut.change_line(3, "3", "3.changed")
117
118
        self.assertEqual(self.uut.modified, result_file)
119
        self.assertEqual(self.uut.original, self.file)
120
121
        self.uut.delete_line(len(self.file))
122
        del result_file[len(result_file) - 1]
123
        self.assertEqual(self.uut.modified, result_file)
124
125
        self.uut.delete_line(1)
126
        del result_file[2]
127
        self.assertEqual(self.uut.modified, result_file)
128
129
    def test_addition(self):
130
        self.assertRaises(TypeError, self.uut.__add__, 5)
131
132
        result_file = ["1",
133
                       "2",
134
                       "2"]
135
136
        other = Diff(self.file)
137
        other.delete_line(1)
138
        other.change_line(2, "1", "2")
139
        other.add_lines(0, ["1"])
140
141
        self.uut.delete_line(1)
142
        self.uut.delete_line(3)
143
        self.uut.change_line(4, "4", "2")
144
        result = self.uut + other
145
146
        self.assertEqual(result.modified, result_file)
147
        # Make sure it didn't happen in place!
148
        self.assertNotEqual(self.uut.modified, result_file)
149
150
    def test_addition_rename(self):
151
        uut = Diff(self.file, rename=False)
152
        other = Diff(self.file, rename=False)
153
        self.assertEqual((other + uut).rename, False)
154
155
        other.rename = "some.py"
156
        self.assertEqual((other + uut).rename, "some.py")
157
158
        uut.rename = "some.py"
159
        self.assertEqual((other + uut).rename, "some.py")
160
161
        uut.rename = "other.py"
162
        self.assertRaises(ConflictError, other.__add__, uut)
163
164
    def test_from_string_arrays(self):
165
        a = ["q", "a", "b", "x", "c", "d"]
166
        b = ["a", "b", "y", "c", "d", "f"]
167
        self.uut = Diff.from_string_arrays(a, b)
168
        self.assertEqual(self.uut.modified, b)
169
170
        a = ["first", "fourth"]
171
        b = ["first", "second", "third", "fourth"]
172
        self.uut = Diff.from_string_arrays(a, b)
173
        self.assertEqual(self.uut.modified, b)
174
175
        a = ["first", "fourth"]
176
        b = ["first_changed", "second", "third", "fourth"]
177
        self.uut = Diff.from_string_arrays(a, b)
178
        self.assertEqual(self.uut.modified, b)
179
180
        a = ["first", "second", "third", "fourth"]
181
        b = ["first", "fourth"]
182
        self.uut = Diff.from_string_arrays(a, b)
183
        self.assertEqual(self.uut.modified, b)
184
185
        a = ["first", "second", "third", "fourth"]
186
        b = ["first_changed", "second_changed", "fourth"]
187
        self.uut = Diff.from_string_arrays(a, b)
188
        self.assertEqual(self.uut.modified, b)
189
190
    def test_from_clang_fixit(self):
191
        try:
192
            from clang.cindex import Index, LibclangError
193
        except ImportError as err:
194
            raise SkipTest(str(err))
195
196
        joined_file = 'struct { int f0; }\nx = { f0 :1 };\n'
197
        file = joined_file.splitlines(True)
198
        fixed_file = ['struct { int f0; }\n', 'x = { .f0 = 1 };\n']
199
        try:
200
            tu = Index.create().parse('t.c', unsaved_files=[
201
                ('t.c', joined_file)])
202
        except LibclangError as err:
203
            raise SkipTest(str(err))
204
205
        fixit = tu.diagnostics[0].fixits[0]
206
        clang_fixed_file = Diff.from_clang_fixit(fixit, file).modified
207
        self.assertEqual(fixed_file, clang_fixed_file)
208
209
    def test_equality(self):
210
        a = ["first", "second", "third"]
211
        b = ["first", "third"]
212
        diff_1 = Diff.from_string_arrays(a, b)
213
214
        a[1] = "else"
215
        diff_2 = Diff.from_string_arrays(a, b)
216
        self.assertEqual(diff_1, diff_2)
217
218
        diff_1.rename = "abcd"
219
        self.assertNotEqual(diff_1, diff_2)
220
        diff_1.rename = False
221
222
        diff_1.delete = True
223
        self.assertNotEqual(diff_1, diff_2)
224
        diff_1.delete = False
225
226
        diff_1.add_lines(1, ["1"])
227
        self.assertNotEqual(diff_1, diff_2)
228
229
    def test_json_export(self):
230
        JSONEncoder = create_json_encoder()
231
        a = ["first\n", "second\n", "third\n"]
232
        b = ["first\n", "third\n"]
233
        diff = Diff.from_string_arrays(a, b)
234
        self.assertEqual(
235
            json.dumps(diff, cls=JSONEncoder, sort_keys=True),
236
            '"--- \\n'
237
            '+++ \\n'
238
            '@@ -1,3 +1,2 @@\\n'
239
            ' first\\n'
240
            '-second\\n'
241
            ' third\\n"')
242
243
    def test_rename(self):
244
        self.uut.rename = False
245
        self.uut.rename = "1234"
246
        with self.assertRaises(TypeError):
247
            self.uut.rename = True
248
        with self.assertRaises(TypeError):
249
            self.uut.rename = 1234
250
251
    def test_delete(self):
252
        self.uut.delete = True
253
        self.uut.delete = False
254
        # Double deletion is allowed
255
        self.uut.delete = False
256
        with self.assertRaises(TypeError):
257
            self.uut.delete = "abcd"
258
259
        # If delete is True then modified returns an empty list
260
        self.uut.delete = True
261
        self.assertEqual(self.uut.modified, [])
262
        self.uut.delete = False
263