1# -*- perl -*-
2
3use strict;
4use Set::IntSpan 1.17;
5
6my $N = 1;
7sub Not { print "not " }
8sub OK
9{
10    my($function, $test) = @_;
11
12    $test ||= [];
13    for (@$test) { defined $_ or $_ = '<undef>' }
14    my $expected = pop @$test;
15
16    print "ok $N $function: @$test\t-> $expected\n";
17
18    $N++;
19}
20
21my @At_die =
22(
23 [ "(-0",  42, "<die>" ],
24 [ "0-)", -42, "<die>" ],
25);
26
27my @At_test =
28(
29 [ "-"	       	     ,   0, undef ],
30 [ "-"	       	     ,  -1, undef ],
31 [ "1-10,20-30"	     ,  25, undef ],
32 [ "1-10,20-30"	     , -25, undef ],
33
34 [ "0-)"       	     ,   0,   0   ],
35 [ "0-)"       	     ,  42,  42   ],
36 [ "(--1"      	     ,  -1,  -1   ],
37 [ "(--1"      	     , -42, -42   ],
38 [ "1-10,20-)" 	     ,  15,  25   ],
39 [ "(--21,-10--1"    , -15, -25   ],
40
41 [ "0-9"             ,   0,   0   ],
42 [ "0-9"             ,   5,   5   ],
43 [ "0-9"             ,   9,   9   ],
44 [ "0-9"             ,  10, undef ],
45
46 [ "0-9"             ,  -1,   9   ],
47 [ "0-9"             ,  -5,   5   ],
48 [ "0-9"             , -10,   0   ],
49 [ "0-9"             , -11, undef ],
50
51 [ "1-10,21-30,41-50",   5,   6   ],
52 [ "1-10,21-30,41-50",  15,  26   ],
53 [ "1-10,21-30,41-50",  25,  46   ],
54 [ "1-10,21-30,41-50",  30, undef ],
55 [ "1-10,21-30,41-50",  -1,  50   ],
56 [ "1-10,21-30,41-50", -11,  30   ],
57 [ "1-10,21-30,41-50", -21,  10   ],
58 [ "1-10,21-30,41-50", -30,   1   ],
59 [ "1-10,21-30,41-50", -31, undef ],
60);
61
62my @Splice_die =
63(
64 [ "(-0"    ,  0,  1, "<die>" ],
65 [ "0-)"    , -1,  1, "<die>" ],
66 [ "0-)"    , -2, -1, "<die>" ],
67 [ "0-)"    ,  0, -1, "<die>" ],
68);
69
70my @Splice_test =
71(
72 # empty sets
73 [ "-"	 	     ,   0,  undef, "-"    	     	],
74 [ "-"	 	     ,   0, 	 0, "-"    	     	],
75 [ "-"	 	     ,   0, 	 1, "-"    	     	],
76 [ "-"	 	     ,   0, 	-1, "-"    	     	],
77
78 # infinite sets
79 [ "0-)"             ,   0,      0, "-"			],
80 [ "0-)"             ,   0,      1, "0"			],
81 [ "0-)"             ,   0,     10, "0-9"		],
82 [ "0-)"             ,   5,      0, "-"			],
83 [ "0-)"             ,   5,      1, "5"			],
84 [ "0-)"             ,   5,     10, "5-14"		],
85 [ "1-10,21-30,41-)" , 	 5,     20, "6-10,21-30,41-45"  ],
86 [ "1-10,21-30,41-)" , 	15,     10, "26-30,41-45"  	],
87
88 [ "(-0"             ,  -1,      0, "-"			],
89 [ "(-0"             ,  -1,      1, "0"			],
90 [ "(-0"             , -10,      5, "-9--5"		],
91 [ "(-0"             , -10,     -3, "-9--3"		],
92 [ "(-10,21-30,41-50", -15,     10, "26-30,41-45"  	],
93 [ "(-10,21-30,41-50", -15,    -10, "26-30"  		],
94 [ "(-10,21-30,41-50", -15,  undef, "26-30,41-50"	],
95
96 # empty slices
97 [ "1-10"	     ,  10,      1, "-"    	     	],
98 [ "1-10"	     ,   5,  	 0, "-"    	     	],
99 [ "1-10"	     ,  -5,  	 0, "-"    	     	],
100 [ "1-10"	     , -10,  	 0, "-"    	     	],
101
102 # positive offset, no length
103 [ "1-10"	     ,   0,  undef, "1-10"  	     	],
104 [ "1-10"	     ,   1,  undef, "2-10" 	     	],
105 [ "1-10"	     ,   5,  undef, "6-10"  	     	],
106 [ "1-10"	     ,   9,  undef, "10"   	     	],
107 [ "1-10"	     ,  10,  undef, "-"    	     	],
108
109 # positive offset, positive length
110 [ "1-10"	     ,   0, 	 3, "1-3"  	     	],
111 [ "1-10"	     ,   5, 	 3, "6-8"  	     	],
112 [ "1-10"	     ,   7, 	 3, "8-10" 	     	],
113 [ "1-10"	     ,   9, 	 1, "10"   	     	],
114 [ "1-10"	     ,  10, 	 1, "-"    	     	],
115 [ "1-10"	     ,   0, 	10, "1-10" 	     	],
116 [ "1-10"	     ,   0, 	20, "1-10" 	     	],
117
118 # positive offset, negative length
119 [ "1-10"	     ,   0, 	-3, "1-7"  	     	],
120 [ "1-10"	     ,   5, 	-3, "6-7"  	     	],
121 [ "1-10"	     ,   6, 	-3, "7"    	     	],
122 [ "1-10"	     ,   7, 	-3, "-"    	     	],
123 [ "1-10"	     ,   8, 	-3, "-"    	     	],
124 [ "1-10"	     ,   9, 	-3, "-"    	     	],
125
126 # negative offset, no length
127 [ "1-10"	     ,  -1,  undef, "10" 	     	],
128 [ "1-10"	     ,  -2,  undef, "9-10"  	     	],
129 [ "1-10"	     ,  -5,  undef, "6-10"  	     	],
130 [ "1-10"	     ,  -9,  undef, "2-10"   	     	],
131 [ "1-10"	     , -10,  undef, "1-10"    	     	],
132
133 # negative offset, positive length
134 [ "1-10"	     ,  -2, 	 2, "9-10" 	     	],
135 [ "1-10"	     ,  -5, 	 2, "6-7"  	     	],
136 [ "1-10"	     , -10, 	 3, "1-3"  	     	],
137 [ "1-10"	     , -10, 	10, "1-10" 	     	],
138 [ "1-10"	     , -10, 	20, "1-10" 	     	],
139 [ "1-10"	     , -20, 	20, "1-10" 	     	],
140
141 # negative offset, negative length
142 [ "1-10"	     , -10,     -3, "1-7"  	     	],
143 [ "1-10"	     ,  -5,     -3, "6-7"  	     	],
144 [ "1-10"	     ,  -5,     -1, "6-9"  	     	],
145 [ "1-10"	     ,  -3,     -3, "-"    	     	],
146 [ "1-10"	     , -10,    -10, "-"    	     	],
147 [ "1-10"	     , -11,    -10, "-"    	     	],
148 [ "1-10"	     , -20,     -9, "1"    	     	],
149 [ "1-10"	     , -20,     -1, "1-9"    	     	],
150
151 [ "1-10,21-30,41-50", 	 0,      0, "-"    	     	],
152
153 # positive offset, no length
154 [ "1-10,21-30,41-50", 	 0,  undef, "1-10,21-30,41-50" 	],
155 [ "1-10,21-30,41-50", 	 9,  undef, "10,21-30,41-50" 	],
156 [ "1-10,21-30,41-50", 	10,  undef, "21-30,41-50" 	],
157 [ "1-10,21-30,41-50", 	19,  undef, "30,41-50" 		],
158 [ "1-10,21-30,41-50", 	20,  undef, "41-50"		],
159 [ "1-10,21-30,41-50", 	29,  undef, "50"		],
160 [ "1-10,21-30,41-50", 	30,  undef, "-"			],
161
162 # positive offset, positive length
163 [ "1-10,21-30,41-50", 	 0,  	 1, "1"    	     	],
164 [ "1-10,21-30,41-50", 	 9,  	 1, "10"   	     	],
165 [ "1-10,21-30,41-50", 	10,  	 1, "21"   	     	],
166 [ "1-10,21-30,41-50", 	19,  	 1, "30"   	     	],
167 [ "1-10,21-30,41-50", 	20,  	 1, "41"   	     	],
168 [ "1-10,21-30,41-50", 	29,  	 1, "50"   	     	],
169
170 [ "1-10,21-30,41-50", 	 0, 	10, "1-10"       	],
171 [ "1-10,21-30,41-50", 	 0, 	11, "1-10,21"    	],
172 [ "1-10,21-30,41-50", 	 0, 	20, "1-10,21-30" 	],
173 [ "1-10,21-30,41-50", 	 0, 	21, "1-10,21-30,41"     ],
174 [ "1-10,21-30,41-50", 	 0, 	30, "1-10,21-30,41-50"  ],
175
176 [ "1-10,21-30,41-50", 	 5, 	10, "6-10,21-25"   	],
177 [ "1-10,21-30,41-50", 	 5, 	11, "6-10,21-26"   	],
178 [ "1-10,21-30,41-50", 	 5, 	20, "6-10,21-30,41-45"  ],
179 [ "1-10,21-30,41-50", 	 5, 	21, "6-10,21-30,41-46"  ],
180 [ "1-10,21-30,41-50", 	 5, 	30, "6-10,21-30,41-50"  ],
181
182 [ "1-10,21-30,41-50", 	15, 	10, "26-30,41-45" 	],
183 [ "1-10,21-30,41-50", 	15, 	11, "26-30,41-46"  	],
184 [ "1-10,21-30,41-50", 	15, 	20, "26-30,41-50" 	],
185 [ "1-10,21-30,41-50", 	15, 	21, "26-30,41-50" 	],
186 [ "1-10,21-30,41-50", 	15, 	30, "26-30,41-50" 	],
187
188 [ "1-10,21-30,41-50", 	25, 	 1, "46" 	   	],
189 [ "1-10,21-30,41-50", 	25, 	 2, "46-47" 	    	],
190 [ "1-10,21-30,41-50", 	25, 	 3, "46-48" 	    	],
191 [ "1-10,21-30,41-50", 	25, 	 5, "46-50" 	    	],
192 [ "1-10,21-30,41-50", 	25, 	 6, "46-50" 	    	],
193 [ "1-10,21-30,41-50", 	25, 	10, "46-50" 	    	],
194
195 # positive offset, negative length
196 [ "1-10,21-30,41-50", 	 0,     -1, "1-10,21-30,41-49"  ],
197 [ "1-10,21-30,41-50", 	 9,     -1, "10,21-30,41-49"    ],
198 [ "1-10,21-30,41-50", 	10,     -1, "21-30,41-49"       ],
199 [ "1-10,21-30,41-50", 	19,     -1, "30,41-49"          ],
200 [ "1-10,21-30,41-50", 	20,     -1, "41-49"             ],
201 [ "1-10,21-30,41-50", 	29,     -1, "-"   	     	],
202
203 [ "1-10,21-30,41-50", 	 0,    -10, "1-10,21-30"  	],
204 [ "1-10,21-30,41-50", 	 0,    -11, "1-10,21-29" 	],
205 [ "1-10,21-30,41-50", 	 0,    -20, "1-10" 	    	],
206 [ "1-10,21-30,41-50", 	 0,    -21, "1-9" 		],
207 [ "1-10,21-30,41-50", 	 0,    -30, "-" 		],
208
209 [ "1-10,21-30,41-50", 	 5,    -10, "6-10,21-30"       	],
210 [ "1-10,21-30,41-50", 	 5,    -11, "6-10,21-29"       	],
211 [ "1-10,21-30,41-50", 	 5,    -20, "6-10" 	    	],
212 [ "1-10,21-30,41-50", 	 5,    -21, "6-9" 	    	],
213 [ "1-10,21-30,41-50", 	 5,    -30, "-" 		],
214
215 [ "1-10,21-30,41-50", 	15,    -10, "26-30" 	    	],
216 [ "1-10,21-30,41-50", 	15,    -11, "26-29" 	    	],
217 [ "1-10,21-30,41-50", 	15,    -20, "-" 		],
218 [ "1-10,21-30,41-50", 	15,    -21, "-" 		],
219 [ "1-10,21-30,41-50", 	15,    -30, "-" 		],
220
221 [ "1-10,21-30,41-50", 	25,     -1, "46-49"   	    	],
222 [ "1-10,21-30,41-50", 	25,     -2, "46-48" 	    	],
223 [ "1-10,21-30,41-50", 	25,     -3, "46-47" 	    	],
224 [ "1-10,21-30,41-50", 	25,     -5, "-" 	    	],
225 [ "1-10,21-30,41-50", 	25,     -6, "-" 	    	],
226 [ "1-10,21-30,41-50", 	25,    -10, "-" 	    	],
227
228 # negative offset, no length
229 [ "1-10,21-30,41-50", 	-1,  undef, "50"		],
230 [ "1-10,21-30,41-50", -10,  undef, "41-50"		],
231 [ "1-10,21-30,41-50", -11,  undef, "30,41-50" 		],
232 [ "1-10,21-30,41-50", -20,  undef, "21-30,41-50" 	],
233 [ "1-10,21-30,41-50", -21,  undef, "10,21-30,41-50" 	],
234 [ "1-10,21-30,41-50", -29,  undef, "2-10,21-30,41-50" 	],
235 [ "1-10,21-30,41-50", -30,  undef, "1-10,21-30,41-50" 	],
236
237 # negative offset, positive length
238 [ "1-10,21-30,41-50", 	-1,  	 1, "50"   	     	],
239 [ "1-10,21-30,41-50", 	-9,  	 1, "42"   	     	],
240 [ "1-10,21-30,41-50", -10,  	 1, "41"   	     	],
241 [ "1-10,21-30,41-50", -19,  	 1, "22"   	     	],
242 [ "1-10,21-30,41-50", -20,  	 1, "21"   	     	],
243 [ "1-10,21-30,41-50", -29,  	 1, "2"   	     	],
244 [ "1-10,21-30,41-50", -30,  	 1, "1"   	     	],
245 [ "1-10,21-30,41-50", -40,  	 1, "1"   	     	],
246
247 [ "1-10,21-30,41-50", 	-1, 	10, "50"       	    	],
248 [ "1-10,21-30,41-50", 	-9, 	10, "42-50"    	    	],
249 [ "1-10,21-30,41-50", -10, 	10, "41-50"    	    	],
250 [ "1-10,21-30,41-50", -19, 	10, "22-30,41"	    	],
251 [ "1-10,21-30,41-50", -30, 	10, "1-10"		],
252 [ "1-10,21-30,41-50", -40, 	10, "1-10"		],
253
254 [ "1-10,21-30,41-50", 	-5, 	 1, "46"   	    	],
255 [ "1-10,21-30,41-50", 	-5, 	 2, "46-47"	    	],
256 [ "1-10,21-30,41-50", 	-5, 	 3, "46-48"	    	],
257 [ "1-10,21-30,41-50", 	-5, 	 5, "46-50"	    	],
258 [ "1-10,21-30,41-50", 	-5, 	 6, "46-50"	    	],
259 [ "1-10,21-30,41-50", 	-5, 	10, "46-50"	    	],
260
261 [ "1-10,21-30,41-50", -15, 	10, "26-30,41-45" 	],
262 [ "1-10,21-30,41-50", -15, 	11, "26-30,41-46"  	],
263 [ "1-10,21-30,41-50", -15, 	20, "26-30,41-50" 	],
264 [ "1-10,21-30,41-50", -15, 	21, "26-30,41-50" 	],
265 [ "1-10,21-30,41-50", -15, 	30, "26-30,41-50" 	],
266
267 [ "1-10,21-30,41-50", -25, 	 1, "6" 	   	],
268 [ "1-10,21-30,41-50", -25, 	 2, "6-7" 	    	],
269 [ "1-10,21-30,41-50", -25, 	 3, "6-8" 	    	],
270 [ "1-10,21-30,41-50", -25, 	 5, "6-10" 	    	],
271 [ "1-10,21-30,41-50", -25, 	 6, "6-10,21" 	    	],
272 [ "1-10,21-30,41-50", -25, 	10, "6-10,21-25" 	],
273
274 # negative offset, negative length
275 [ "1-10,21-30,41-50", 	-1, 	-1, "-"   	     	],
276 [ "1-10,21-30,41-50", 	-9, 	-1, "42-49"    		],
277 [ "1-10,21-30,41-50", -10, 	-1, "41-49"    		],
278 [ "1-10,21-30,41-50", -19, 	-1, "22-30,41-49"       ],
279 [ "1-10,21-30,41-50", -20, 	-1, "21-30,41-49"       ],
280 [ "1-10,21-30,41-50", -29, 	-1, "2-10,21-30,41-49"  ],
281 [ "1-10,21-30,41-50", -31, 	-1, "1-10,21-30,41-49"  ],
282
283 [ "1-10,21-30,41-50", 	-5, 	-1, "46-49"	       	],
284 [ "1-10,21-30,41-50", 	-5, 	-2, "46-48"	       	],
285 [ "1-10,21-30,41-50", 	-5, 	-4, "46"	 	],
286 [ "1-10,21-30,41-50", 	-5, 	-5, "-" 		],
287 [ "1-10,21-30,41-50", 	-5, 	-7, "-" 		],
288
289 [ "1-10,21-30,41-50", -15,    -10, "26-30" 	    	],
290 [ "1-10,21-30,41-50", -15,    -11, "26-29" 	    	],
291 [ "1-10,21-30,41-50", -15,    -20, "-" 		],
292 [ "1-10,21-30,41-50", -15,    -21, "-" 		],
293 [ "1-10,21-30,41-50", -15,    -30, "-" 		],
294
295 [ "1-10,21-30,41-50", -25,     -1, "6-10,21-30,41-49"  ],
296 [ "1-10,21-30,41-50", -25,     -2, "6-10,21-30,41-48"  ],
297 [ "1-10,21-30,41-50", -25,     -9, "6-10,21-30,41"   	],
298 [ "1-10,21-30,41-50", -25,    -10, "6-10,21-30"   	],
299 [ "1-10,21-30,41-50", -25,    -11, "6-10,21-29"   	],
300 [ "1-10,21-30,41-50", -25,    -24, "6"		   	],
301 [ "1-10,21-30,41-50", -25,    -25, "-"		   	],
302
303 [ "1-10,21-30,41-50", -30,    -10, "1-10,21-30"  	],
304 [ "1-10,21-30,41-50", -30,    -11, "1-10,21-29" 	],
305 [ "1-10,21-30,41-50", -30,    -20, "1-10" 	    	],
306 [ "1-10,21-30,41-50", -30,    -21, "1-9" 		],
307 [ "1-10,21-30,41-50", -30,    -30, "-" 		],
308
309 [ "1-10,21-30,41-50", -35,    -10, "1-10,21-30"  	],
310 [ "1-10,21-30,41-50", -35,    -11, "1-10,21-29" 	],
311 [ "1-10,21-30,41-50", -35,    -20, "1-10" 	    	],
312 [ "1-10,21-30,41-50", -35,    -21, "1-9" 		],
313 [ "1-10,21-30,41-50", -35,    -30, "-" 		],
314
315);
316
317my @Slice_die =
318(
319 [ "(-0"    ,  0,  1, "<die>" ],
320 [ "0-)"    , -2, -1, "<die>" ],
321);
322
323my @Slice_test =
324(
325 # empty sets
326 [ "-"	 	     ,   0,      0, "-"    	     	],
327 [ "-"	 	     ,   0, 	 1, "-"    	     	],
328 [ "-"	 	     ,  -2, 	-1, "-"    	     	],
329
330 # infinite sets
331 [ "0-)"             ,   0,      0, "0"			],
332 [ "0-)"             ,   0,      1, "0-1"		],
333 [ "0-)"             ,   0,      9, "0-9"		],
334 [ "0-)"             ,   5,      4, "-"			],
335 [ "0-)"             ,   5,      5, "5"			],
336 [ "0-)"             ,   5,     14, "5-14"		],
337 [ "1-10,21-30,41-)" , 	 5,     24, "6-10,21-30,41-45"  ],
338 [ "1-10,21-30,41-)" , 	15,     24, "26-30,41-45"  	],
339
340 [ "(-0"             ,  -1,      0, "0"			],
341 [ "(-0"             ,  -2,     -1, "-1-0"		],
342 [ "(-0"             , -10,     -6, "-9--5"		],
343 [ "(-0"             , -10,     -4, "-9--3"		],
344 [ "(-10,21-30,41-50", -15,     -6, "26-30,41-45"  	],
345 [ "(-10,21-30,41-50", -15,    -11, "26-30"  		],
346
347 # empty slices
348 [ "1-10"	     ,  10,     11, "-"    	     	],
349 [ "1-10"	     ,   5,  	 4, "-"    	     	],
350 [ "1-10"	     ,  -5,  	-6, "-"    	     	],
351 [ "1-10"	     , -12,    -11, "-"    	     	],
352
353 # positive indices
354 [ "1-10"	     ,   0, 	 2, "1-3"  	     	],
355 [ "1-10"	     ,   5, 	 7, "6-8"  	     	],
356 [ "1-10"	     ,   7, 	 9, "8-10" 	     	],
357 [ "1-10"	     ,   9, 	 9, "10"   	     	],
358 [ "1-10"	     ,  10, 	10, "-"    	     	],
359 [ "1-10"	     ,   0, 	 9, "1-10" 	     	],
360 [ "1-10"	     ,   0, 	20, "1-10" 	     	],
361
362 # negative indices
363 [ "1-10"	     ,  -2, 	-1, "9-10" 	     	],
364 [ "1-10"	     ,  -5, 	-4, "6-7"  	     	],
365 [ "1-10"	     , -10, 	-8, "1-3"  	     	],
366 [ "1-10"	     , -10, 	-1, "1-10" 	     	],
367 [ "1-10"	     , -10, 	20, "1-10" 	     	],
368
369);
370
371
372print "1..", @At_die + @At_test + @Splice_die + @Splice_test + @Slice_die + @Slice_test, "\n";
373
374
375for my $test (@At_die)
376{
377    my($run_list, $i) = @$test;
378
379    eval { Set::IntSpan->new($run_list)->at($i) };
380    $@ or Not; OK("at", $test);
381}
382
383for my $test (@At_test)
384{
385    my($run_list, $i, $n) = @$test;
386
387    equal(Set::IntSpan->new($run_list)->at($i), $n) or Not; OK("at", $test);
388}
389
390sub equal
391{
392    my($a, $b) = @_;
393
394    not defined $a and not defined $b or
395        defined $a and     defined $b and $a == $b
396}
397
398for my $test (@Splice_die)
399{
400    my($run_list, $offset, $length) = @$test;
401
402    eval { Set::IntSpan->new($run_list)->_splice($offset, $length) };
403    $@ or Not; OK("splice", $test);
404}
405
406for my $test (@Splice_test)
407{
408    my($run_list, $offset, $length, $expected) = @$test;
409
410    my $actual = Set::IntSpan->new($run_list)->_splice($offset, $length)->run_list;
411    $actual eq $expected or Not; OK("splice", $test);
412#   $actual eq $expected or print "\t$actual\n";
413}
414
415for my $test (@Slice_die)
416{
417    my($run_list, $offset, $length) = @$test;
418
419    eval { Set::IntSpan->new($run_list)->slice($offset, $length) };
420    $@ or Not; OK("slice", $test);
421}
422
423for my $test (@Slice_test)
424{
425    my($run_list, $offset, $length, $expected) = @$test;
426
427    my $actual = Set::IntSpan->new($run_list)->slice($offset, $length)->run_list;
428    $actual eq $expected or Not; OK("slice", $test);
429#   $actual eq $expected or print "\t$actual\n";
430}
431