1#!/usr/bin/perl -w
2#
3# Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
4# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
5# Copyright (C) 2012 Daniel Bates (dbates@intudata.com)
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions are
9# met:
10#
11#     * Redistributions of source code must retain the above copyright
12# notice, this list of conditions and the following disclaimer.
13#     * Redistributions in binary form must reproduce the above
14# copyright notice, this list of conditions and the following disclaimer
15# in the documentation and/or other materials provided with the
16# distribution.
17#     * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
18# its contributors may be used to endorse or promote products derived
19# from this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33# Unit tests of parseSvnDiffProperties().
34
35use strict;
36use warnings;
37
38use Test::More;
39use VCSUtils;
40
41my @testCaseHashRefs = (
42####
43# Simple test cases
44##
45{
46    # New test
47    diffName => "simple: add svn:executable",
48    inputText => <<'END',
49Property changes on: FileA
50___________________________________________________________________
51Added: svn:executable
52   + *
53END
54    expectedReturn => [
55{
56    propertyPath => "FileA",
57    executableBitDelta => 1,
58},
59undef],
60    expectedNextLine => undef,
61},
62{
63    # New test
64    diffName => "simple: add svn:mergeinfo",
65    inputText => <<'END',
66Property changes on: Makefile
67___________________________________________________________________
68Added: svn:mergeinfo
69   Merged /trunk/Makefile:r33020
70END
71    expectedReturn => [
72{
73    propertyPath => "Makefile",
74},
75undef],
76    expectedNextLine => undef,
77},
78{
79    # New test
80    diffName => "simple: delete svn:mergeinfo",
81    inputText => <<'END',
82Property changes on: Makefile
83___________________________________________________________________
84Deleted: svn:mergeinfo
85   Reverse-merged /trunk/Makefile:r33020
86END
87    expectedReturn => [
88{
89    propertyPath => "Makefile",
90},
91undef],
92    expectedNextLine => undef,
93},
94{
95    # New test
96    diffName => "simple: modified svn:mergeinfo",
97    inputText => <<'END',
98Property changes on: Makefile
99___________________________________________________________________
100Modified: svn:mergeinfo
101   Reverse-merged /trunk/Makefile:r33020
102   Merged /trunk/Makefile:r41697
103END
104    expectedReturn => [
105{
106    propertyPath => "Makefile",
107},
108undef],
109    expectedNextLine => undef,
110},
111{
112    # New test
113    diffName => "simple: delete svn:executable",
114    inputText => <<'END',
115Property changes on: FileA
116___________________________________________________________________
117Deleted: svn:executable
118   - *
119END
120    expectedReturn => [
121{
122    propertyPath => "FileA",
123    executableBitDelta => -1,
124},
125undef],
126    expectedNextLine => undef,
127},
128{
129    # New test
130    diffName => "simple: delete svn:executable using SVN 1.4 syntax",
131    inputText => <<'END',
132Property changes on: FileA
133___________________________________________________________________
134Name: svn:executable
135   - *
136END
137    expectedReturn => [
138{
139    propertyPath => "FileA",
140    executableBitDelta => -1,
141},
142undef],
143    expectedNextLine => undef,
144},
145####
146# Property value followed by empty line and start of next diff
147##
148{
149    # New test
150    diffName => "add svn:executable, followed by empty line and start of next diff",
151    inputText => <<'END',
152Property changes on: FileA
153___________________________________________________________________
154Added: svn:executable
155   + *
156
157Index: Makefile.shared
158END
159    expectedReturn => [
160{
161    propertyPath => "FileA",
162    executableBitDelta => 1,
163},
164"\n"],
165    expectedNextLine => "Index: Makefile.shared\n",
166},
167{
168    # New test
169    diffName => "add svn:executable, followed by empty line and start of next property diff",
170    inputText => <<'END',
171Property changes on: FileA
172___________________________________________________________________
173Added: svn:executable
174   + *
175
176Property changes on: Makefile.shared
177END
178    expectedReturn => [
179{
180    propertyPath => "FileA",
181    executableBitDelta => 1,
182},
183"\n"],
184    expectedNextLine => "Property changes on: Makefile.shared\n",
185},
186####
187# Property value followed by empty line and start of the binary contents
188##
189{
190    # New test
191    diffName => "add svn:executable, followed by empty line and start of binary contents",
192    inputText => <<'END',
193Property changes on: FileA
194___________________________________________________________________
195Added: svn:executable
196   + *
197
198Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
199END
200    expectedReturn => [
201{
202    propertyPath => "FileA",
203    executableBitDelta => 1,
204},
205"\n"],
206    expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
207},
208{
209    # New test
210    diffName => "custom property followed by svn:executable, empty line and start of binary contents",
211    inputText => <<'END',
212Property changes on: FileA
213___________________________________________________________________
214Added: documentation
215   + This is an example sentence.
216Added: svn:executable
217   + *
218
219Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
220END
221    expectedReturn => [
222{
223    propertyPath => "FileA",
224    executableBitDelta => 1,
225},
226"\n"],
227    expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
228},
229####
230# Successive properties
231##
232{
233    # New test
234    diffName => "svn:executable followed by custom property",
235    inputText => <<'END',
236Property changes on: FileA
237___________________________________________________________________
238Added: svn:executable
239   + *
240Added: documentation
241   + This is an example sentence.
242END
243    expectedReturn => [
244{
245    propertyPath => "FileA",
246    executableBitDelta => 1,
247},
248undef],
249    expectedNextLine => undef,
250},
251{
252    # New test
253    diffName => "svn:executable followed by custom property using SVN 1.7 syntax",
254    inputText => <<'END',
255Property changes on: FileA
256___________________________________________________________________
257Added: svn:executable
258## -0,0 +1 ##
259+*
260\ No newline at end of property
261Added: documentation
262## -0,0 +1 ##
263+This is an example sentence.
264END
265    expectedReturn => [
266{
267    propertyPath => "FileA",
268    executableBitDelta => 1,
269},
270undef],
271    expectedNextLine => undef,
272},
273{
274    # New test
275    diffName => "svn:executable followed by custom property without newline using SVN 1.7 syntax",
276    inputText => <<'END',
277Property changes on: FileA
278___________________________________________________________________
279Added: svn:executable
280## -0,0 +1 ##
281+*
282\ No newline at end of property
283Added: documentation
284## -0,0 +1 ##
285+This is an example sentence.
286\ No newline at end of property
287END
288    expectedReturn => [
289{
290    propertyPath => "FileA",
291    executableBitDelta => 1,
292},
293undef],
294    expectedNextLine => undef,
295},
296{
297    # New test
298    diffName => "custom property followed by svn:executable",
299    inputText => <<'END',
300Property changes on: FileA
301___________________________________________________________________
302Added: documentation
303   + This is an example sentence.
304Added: svn:executable
305   + *
306END
307    expectedReturn => [
308{
309    propertyPath => "FileA",
310    executableBitDelta => 1,
311},
312undef],
313    expectedNextLine => undef,
314},
315####
316# Successive properties followed by empty line and start of next diff
317##
318{
319    # New test
320    diffName => "custom property followed by svn:executable, empty line and start of next property diff",
321    inputText => <<'END',
322Property changes on: FileA
323___________________________________________________________________
324Added: documentation
325   + This is an example sentence.
326Added: svn:executable
327   + *
328
329Property changes on: Makefile.shared
330END
331    expectedReturn => [
332{
333    propertyPath => "FileA",
334    executableBitDelta => 1,
335},
336"\n"],
337    expectedNextLine => "Property changes on: Makefile.shared\n",
338},
339{
340    # New test
341    diffName => "custom property followed by svn:executable, empty line and start of next index diff",
342    inputText => <<'END',
343Property changes on: FileA
344___________________________________________________________________
345Added: documentation
346   + This is an example sentence.
347Added: svn:executable
348   + *
349
350Index: Makefile.shared
351END
352    expectedReturn => [
353{
354    propertyPath => "FileA",
355    executableBitDelta => 1,
356},
357"\n"],
358    expectedNextLine => "Index: Makefile.shared\n",
359},
360####
361# Custom properties
362##
363# FIXME: We do not support anything other than the svn:executable property.
364#        We should add support for handling other properties.
365{
366    # New test
367    diffName => "simple: custom property",
368    inputText => <<'END',
369Property changes on: FileA
370___________________________________________________________________
371Name: documentation
372   + This is an example sentence.
373END
374    expectedReturn => [
375{
376    propertyPath => "FileA",
377},
378undef],
379    expectedNextLine => undef,
380},
381{
382    # New test
383    diffName => "custom property followed by custom property",
384    inputText => <<'END',
385Property changes on: FileA
386___________________________________________________________________
387Added: copyright
388   + Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
389Added: documentation
390   + This is an example sentence.
391END
392    expectedReturn => [
393{
394    propertyPath => "FileA",
395},
396undef],
397    expectedNextLine => undef,
398},
399####
400# Malformed property diffs
401##
402# We shouldn't encounter such diffs in practice.
403{
404    # New test
405    diffName => "svn:executable followed by custom property and svn:executable",
406    inputText => <<'END',
407Property changes on: FileA
408___________________________________________________________________
409Added: svn:executable
410   + *
411Added: documentation
412   + This is an example sentence.
413Deleted: svn:executable
414   - *
415END
416    expectedReturn => [
417{
418    propertyPath => "FileA",
419    executableBitDelta => -1,
420},
421undef],
422    expectedNextLine => undef,
423},
424);
425
426my $testCasesCount = @testCaseHashRefs;
427plan(tests => 2 * $testCasesCount); # Total number of assertions.
428
429foreach my $testCase (@testCaseHashRefs) {
430    my $testNameStart = "parseSvnDiffProperties(): $testCase->{diffName}: comparing";
431
432    my $fileHandle;
433    open($fileHandle, "<", \$testCase->{inputText});
434    my $line = <$fileHandle>;
435
436    my @got = VCSUtils::parseSvnDiffProperties($fileHandle, $line);
437    my $expectedReturn = $testCase->{expectedReturn};
438
439    is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
440
441    my $gotNextLine = <$fileHandle>;
442    is($gotNextLine, $testCase->{expectedNextLine},  "$testNameStart next read line.");
443}
444