1ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport difflib
2ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehfrom test.test_support import run_unittest, findfile
3ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport unittest
4ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport doctest
5ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehimport sys
6ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
7ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
8ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestWithAscii(unittest.TestCase):
9ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_one_insert(self):
10ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        sm = difflib.SequenceMatcher(None, 'b' * 100, 'a' + 'b' * 100)
11ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertAlmostEqual(sm.ratio(), 0.995, places=3)
12ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(sm.get_opcodes()),
13ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            [   ('insert', 0, 0, 0, 1),
14ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('equal', 0, 100, 1, 101)])
15ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        sm = difflib.SequenceMatcher(None, 'b' * 100, 'b' * 50 + 'a' + 'b' * 50)
16ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertAlmostEqual(sm.ratio(), 0.995, places=3)
17ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(sm.get_opcodes()),
18ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            [   ('equal', 0, 50, 0, 50),
19ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('insert', 50, 50, 50, 51),
20ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('equal', 50, 100, 51, 101)])
21ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
22ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_one_delete(self):
23ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        sm = difflib.SequenceMatcher(None, 'a' * 40 + 'c' + 'b' * 40, 'a' * 40 + 'b' * 40)
24ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertAlmostEqual(sm.ratio(), 0.994, places=3)
25ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(sm.get_opcodes()),
26ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            [   ('equal', 0, 40, 0, 40),
27ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('delete', 40, 41, 40, 40),
28ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                ('equal', 41, 81, 40, 80)])
29ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
30ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
31ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestAutojunk(unittest.TestCase):
32ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    """Tests for the autojunk parameter added in 2.7"""
33ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_one_insert_homogenous_sequence(self):
34ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # By default autojunk=True and the heuristic kicks in for a sequence
35ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # of length 200+
36ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        seq1 = 'b' * 200
37ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        seq2 = 'a' + 'b' * 200
38ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
39ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        sm = difflib.SequenceMatcher(None, seq1, seq2)
40ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertAlmostEqual(sm.ratio(), 0, places=3)
41ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
42ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Now turn the heuristic off
43ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        sm = difflib.SequenceMatcher(None, seq1, seq2, autojunk=False)
44ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertAlmostEqual(sm.ratio(), 0.9975, places=3)
45ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
46ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
47ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestSFbugs(unittest.TestCase):
48ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_ratio_for_null_seqn(self):
49ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Check clearing of SF bug 763023
50ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        s = difflib.SequenceMatcher(None, [], [])
51ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(s.ratio(), 1)
52ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(s.quick_ratio(), 1)
53ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(s.real_quick_ratio(), 1)
54ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
55ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_comparing_empty_lists(self):
56ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Check fix for bug #979794
57ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        group_gen = difflib.SequenceMatcher(None, [], []).get_grouped_opcodes()
58ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(StopIteration, group_gen.next)
59ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        diff_gen = difflib.unified_diff([], [])
60ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertRaises(StopIteration, diff_gen.next)
61ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
62ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_added_tab_hint(self):
63ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Check fix for bug #1488943
64ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        diff = list(difflib.Differ().compare(["\tI am a buggy"],["\t\tI am a bug"]))
65ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual("- \tI am a buggy", diff[0])
66ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual("?            --\n", diff[1])
67ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual("+ \t\tI am a bug", diff[2])
68ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual("? +\n", diff[3])
69ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
70ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpatch914575_from1 = """
71ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   1. Beautiful is beTTer than ugly.
72ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   2. Explicit is better than implicit.
73ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   3. Simple is better than complex.
74ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   4. Complex is better than complicated.
75ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
76ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
77ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpatch914575_to1 = """
78ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   1. Beautiful is better than ugly.
79ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   3.   Simple is better than complex.
80ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   4. Complicated is better than complex.
81ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh   5. Flat is better than nested.
82ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
83ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
84ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpatch914575_from2 = """
85ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh\t\tLine 1: preceeded by from:[tt] to:[ssss]
86ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh  \t\tLine 2: preceeded by from:[sstt] to:[sssst]
87ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh  \t \tLine 3: preceeded by from:[sstst] to:[ssssss]
88ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehLine 4:  \thas from:[sst] to:[sss] after :
89ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehLine 5: has from:[t] to:[ss] at end\t
90ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
91ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
92ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpatch914575_to2 = """
93ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    Line 1: preceeded by from:[tt] to:[ssss]
94ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    \tLine 2: preceeded by from:[sstt] to:[sssst]
95ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh      Line 3: preceeded by from:[sstst] to:[ssssss]
96ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehLine 4:   has from:[sst] to:[sss] after :
97ffab958fd8d42ed7227d83007350e61555a1fa36Andrew HsiehLine 5: has from:[t] to:[ss] at end
98ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh"""
99ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
100ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpatch914575_from3 = """line 0
101ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh1234567890123456789012345689012345
102ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 1
103ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 2
104ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 3
105ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 4   changed
106ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 5   changed
107ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 6   changed
108ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 7
109ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 8  subtracted
110ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 9
111ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh1234567890123456789012345689012345
112ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehshort line
113ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehjust fits in!!
114ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehjust fits in two lines yup!!
115ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehthe end"""
116ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
117ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehpatch914575_to3 = """line 0
118ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh1234567890123456789012345689012345
119ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 1
120ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 2    added
121ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 3
122ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 4   chanGEd
123ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 5a  chanGed
124ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 6a  changEd
125ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 7
126ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 8
127ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehline 9
128ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh1234567890
129ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehanother long line that needs to be wrapped
130ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehjust fitS in!!
131ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehjust fits in two lineS yup!!
132ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehthe end"""
133ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
134ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestSFpatches(unittest.TestCase):
135ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
136ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_html_diff(self):
137ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Check SF patch 914575 for generating HTML differences
138ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f1a = ((patch914575_from1 + '123\n'*10)*3)
139ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t1a = (patch914575_to1 + '123\n'*10)*3
140ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f1b = '456\n'*10 + f1a
141ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t1b = '456\n'*10 + t1a
142ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f1a = f1a.splitlines()
143ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t1a = t1a.splitlines()
144ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f1b = f1b.splitlines()
145ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t1b = t1b.splitlines()
146ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f2 = patch914575_from2.splitlines()
147ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t2 = patch914575_to2.splitlines()
148ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        f3 = patch914575_from3
149ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        t3 = patch914575_to3
150ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        i = difflib.HtmlDiff()
151ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        j = difflib.HtmlDiff(tabsize=2)
152ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        k = difflib.HtmlDiff(wrapcolumn=14)
153ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
154ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        full = i.make_file(f1a,t1a,'from','to',context=False,numlines=5)
155ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        tables = '\n'.join(
156ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            [
157ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Context (first diff within numlines=5(default))</h2>',
158ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f1a,t1a,'from','to',context=True),
159ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Context (first diff after numlines=5(default))</h2>',
160ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f1b,t1b,'from','to',context=True),
161ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Context (numlines=6)</h2>',
162ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f1a,t1a,'from','to',context=True,numlines=6),
163ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Context (numlines=0)</h2>',
164ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f1a,t1a,'from','to',context=True,numlines=0),
165ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Same Context</h2>',
166ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f1a,f1a,'from','to',context=True),
167ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Same Full</h2>',
168ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f1a,f1a,'from','to',context=False),
169ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Empty Context</h2>',
170ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table([],[],'from','to',context=True),
171ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Empty Full</h2>',
172ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table([],[],'from','to',context=False),
173ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>tabsize=2</h2>',
174ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             j.make_table(f2,t2),
175ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>tabsize=default</h2>',
176ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             i.make_table(f2,t2),
177ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>Context (wrapcolumn=14,numlines=0)</h2>',
178ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             k.make_table(f3.splitlines(),t3.splitlines(),context=True,numlines=0),
179ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>wrapcolumn=14,splitlines()</h2>',
180ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             k.make_table(f3.splitlines(),t3.splitlines()),
181ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             '<h2>wrapcolumn=14,splitlines(True)</h2>',
182ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             k.make_table(f3.splitlines(True),t3.splitlines(True)),
183ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             ])
184ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        actual = full.replace('</body>','\n%s\n</body>' % tables)
185ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
186ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # temporarily uncomment next two lines to baseline this test
187ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #with open('test_difflib_expect.html','w') as fp:
188ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        #    fp.write(actual)
189ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
190ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        with open(findfile('test_difflib_expect.html')) as fp:
191ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            self.assertEqual(actual, fp.read())
192ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
193ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_recursion_limit(self):
194ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Check if the problem described in patch #1413711 exists.
195ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        limit = sys.getrecursionlimit()
196ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        old = [(i%2 and "K:%d" or "V:A:%d") % i for i in range(limit*2)]
197ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        new = [(i%2 and "K:%d" or "V:B:%d") % i for i in range(limit*2)]
198ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        difflib.SequenceMatcher(None, old, new).get_opcodes()
199ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
200ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
201ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehclass TestOutputFormat(unittest.TestCase):
202ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_tab_delimiter(self):
203ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        args = ['one', 'two', 'Original', 'Current',
204ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            '2005-01-26 23:30:50', '2010-04-02 10:20:52']
205ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ud = difflib.unified_diff(*args, lineterm='')
206ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(ud)[0:2], [
207ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           "--- Original\t2005-01-26 23:30:50",
208ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           "+++ Current\t2010-04-02 10:20:52"])
209ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        cd = difflib.context_diff(*args, lineterm='')
210ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(cd)[0:2], [
211ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           "*** Original\t2005-01-26 23:30:50",
212ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh                           "--- Current\t2010-04-02 10:20:52"])
213ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
214ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_no_trailing_tab_on_empty_filedate(self):
215ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        args = ['one', 'two', 'Original', 'Current']
216ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        ud = difflib.unified_diff(*args, lineterm='')
217ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(ud)[0:2], ["--- Original", "+++ Current"])
218ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
219ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        cd = difflib.context_diff(*args, lineterm='')
220ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(list(cd)[0:2], ["*** Original", "--- Current"])
221ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
222ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_range_format_unified(self):
223ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Per the diff spec at http://www.unix.org/single_unix_specification/
224ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        spec = '''\
225ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           Each <range> field shall be of the form:
226ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh             %1d", <beginning line number>  if the range contains exactly one line,
227ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           and:
228ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh            "%1d,%1d", <beginning line number>, <number of lines> otherwise.
229ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           If a range is empty, its beginning line number shall be the number of
230ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           the line just before the range, or 0 if the empty range starts the file.
231ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        '''
232ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        fmt = difflib._format_range_unified
233ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,3), '3,0')
234ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,4), '4')
235ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,5), '4,2')
236ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,6), '4,3')
237ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(0,0), '0,0')
238ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
239ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    def test_range_format_context(self):
240ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        # Per the diff spec at http://www.unix.org/single_unix_specification/
241ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        spec = '''\
242ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           The range of lines in file1 shall be written in the following format
243ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           if the range contains two or more lines:
244ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh               "*** %d,%d ****\n", <beginning line number>, <ending line number>
245ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           and the following format otherwise:
246ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh               "*** %d ****\n", <ending line number>
247ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           The ending line number of an empty range shall be the number of the preceding line,
248ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           or 0 if the range is at the start of the file.
249ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
250ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           Next, the range of lines in file2 shall be written in the following format
251ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           if the range contains two or more lines:
252ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh               "--- %d,%d ----\n", <beginning line number>, <ending line number>
253ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh           and the following format otherwise:
254ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh               "--- %d ----\n", <ending line number>
255ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        '''
256ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        fmt = difflib._format_range_context
257ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,3), '3')
258ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,4), '4')
259ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,5), '4,5')
260ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(3,6), '4,6')
261ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        self.assertEqual(fmt(0,0), '0')
262ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
263ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
264ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehdef test_main():
265ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    difflib.HtmlDiff._default_prefix = 0
266ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    Doctests = doctest.DocTestSuite(difflib)
267ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    run_unittest(
268ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs,
269ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh        TestOutputFormat, Doctests)
270ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh
271ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsiehif __name__ == '__main__':
272ffab958fd8d42ed7227d83007350e61555a1fa36Andrew Hsieh    test_main()
273