1 package io.jawk.posix;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import io.jawk.AwkTestSupport;
26 import java.util.Locale;
27 import org.junit.AfterClass;
28 import org.junit.BeforeClass;
29 import org.junit.Test;
30
31
32
33
34
35
36
37
38 public class PosixIT {
39
40 private static Locale defaultLocale;
41
42 @BeforeClass
43 public static void captureLocale() {
44 defaultLocale = Locale.getDefault();
45 Locale.setDefault(Locale.US);
46 }
47
48 @AfterClass
49 public static void resetLocale() {
50 if (defaultLocale != null) {
51 Locale.setDefault(defaultLocale);
52 }
53 }
54
55 @Test
56 public void spec01VisibleInBegin() throws Exception {
57 AwkTestSupport
58 .awkTest("1. -v visible in BEGIN")
59 .script("BEGIN{print X}")
60 .preassign("X", "42")
61 .expectLines("42")
62 .runAndAssert();
63 }
64
65 @Test
66 public void spec02OperandAssignmentAfterBegin() throws Exception {
67 AwkTestSupport
68 .awkTest("2. Operand assignment after BEGIN")
69 .script("BEGIN{print (X==\"\"?\"unset\":\"set\")} {print X \":\" $0}")
70 .file("a.txt", "one\n")
71 .operand("X=abc", "{{a.txt}}")
72 .expectLines("unset", "abc:one")
73 .runAndAssert();
74 }
75
76 @Test
77 public void spec03OperandAssignmentPerFile() throws Exception {
78 AwkTestSupport
79 .awkTest("3. Operand assignment per file")
80 .script("{print FILENAME \":\" X \":\" $0}")
81 .file("A", "a1\na2\n")
82 .file("B", "b1\nb2\n")
83 .operand("X=AA", "{{A}}", "X=BB", "{{B}}")
84 .expectLines("{{A}}:AA:a1", "{{A}}:AA:a2", "{{B}}:BB:b1", "{{B}}:BB:b2")
85 .runAndAssert();
86 }
87
88 @Test
89 public void spec04BeginOnlyDoesNotReadFiles() throws Exception {
90 AwkTestSupport
91 .awkTest("4. BEGIN-only does not read files")
92 .script("BEGIN{print \"hi\"}")
93 .file("a.txt", "anything\n")
94 .operand("{{a.txt}}")
95 .expectLines("hi")
96 .runAndAssert();
97 }
98
99 @Test
100 public void spec05EndReadsInput() throws Exception {
101 AwkTestSupport
102 .awkTest("5. END reads input")
103 .script("END{print NR}")
104 .file("a.txt", "x\ny\n")
105 .operand("{{a.txt}}")
106 .expectLines("2")
107 .runAndAssert();
108 }
109
110 @Test
111 public void spec06DefaultRsIsNewline() throws Exception {
112 AwkTestSupport
113 .awkTest("6. Default RS is newline")
114 .script("{print $0}")
115 .stdin("a\nb\nc\n")
116 .expectLines("a", "b", "c")
117 .runAndAssert();
118 }
119
120 @Test
121 public void spec07RsSingleCharacter() throws Exception {
122 AwkTestSupport
123 .awkTest("7. RS single character")
124 .script("BEGIN{RS=\",\"}{print $0}")
125 .stdin("a,b,c")
126 .expectLines("a", "b", "c")
127 .runAndAssert();
128 }
129
130 @Test
131 public void spec08RsEmptyParagraphMode() throws Exception {
132 AwkTestSupport
133 .awkTest("8. RS empty paragraph mode")
134 .script(
135 "BEGIN{RS=\"\"}{n=split($0, lines, \"\\\\n\"); count=0; for(i=1;i<=n;i++){if(lines[i]!=\"\"){count++}}; print \"REC:\" NR \":\" count \"lines\"}")
136 .stdin("p1-line1\n\n\np2-line1\np2-line2\n\np3\n")
137 .expectLines("REC:1:4lines")
138 .runAndAssert();
139 }
140
141 @Test
142 public void spec09DefaultFsCollapsesBlanks() throws Exception {
143 AwkTestSupport
144 .awkTest("9. Default FS collapses blanks")
145 .script("{print NF \":\" $1 \":\" $2 \":\" $3}")
146 .stdin(" a\tb c")
147 .expectLines("3:a:b:c")
148 .runAndAssert();
149 }
150
151 @Test
152 public void spec10FsCommaPreservesEmpties() throws Exception {
153 AwkTestSupport
154 .awkTest("10. FS comma preserves empties")
155 .script("BEGIN{FS=\",\"}{print NF \":\" $1 \":\" $2 \":\" $3 \":\" $4}")
156 .stdin("a,,b,c,")
157 .expectLines("5:a::b:c")
158 .runAndAssert();
159 }
160
161 @Test
162 public void spec11FsAsEre() throws Exception {
163 AwkTestSupport
164 .awkTest("11. FS as ERE")
165 .script("BEGIN{FS=\"[ ,:]+\"}{print NF \":\" $1 \":\" $2 \":\" $3}")
166 .stdin("a,, b:::c")
167 .expectLines("3:a:b:c")
168 .runAndAssert();
169 }
170
171 @Test
172 public void spec12FsChangeAffectsFutureRecords() throws Exception {
173 AwkTestSupport
174 .awkTest("12. FS change affects future records")
175 .script("NR==1{print NF \":\" $1 \":\" $2; FS=\",\"} NR==2{print NF \":\" $1 \":\" $2}")
176 .stdin("a b\nc,d\n")
177 .expectLines("2:a:b", "2:c:d")
178 .runAndAssert();
179 }
180
181 @Test
182 public void spec13AssigningToZeroRecomputesFields() throws Exception {
183 AwkTestSupport
184 .awkTest("13. Assigning to $0 recomputes fields")
185 .script("{$0=\"p q r\"; print NF \":\" $2}")
186 .stdin("x y\n")
187 .expectLines("3:q")
188 .runAndAssert();
189 }
190
191 @Test
192 public void spec14AssigningToFieldRebuildsZero() throws Exception {
193 AwkTestSupport
194 .awkTest("14. Assigning to field rebuilds $0")
195 .script("{$2=\"X\"; print $0}")
196 .stdin("a b c\n")
197 .expectLines("a X c")
198 .runAndAssert();
199 }
200
201 @Test
202 public void spec15ReferencingFieldPastNf() throws Exception {
203 AwkTestSupport
204 .awkTest("15. Referencing field past NF")
205 .script("{print \"(\" $(NF+1) \"):\" NF}")
206 .stdin("a b\n")
207 .expectLines("():2")
208 .runAndAssert();
209 }
210
211 @Test
212 public void spec16AssigningBeyondNfGrowsRecord() throws Exception {
213 AwkTestSupport
214 .awkTest("16. Assigning beyond NF grows record")
215 .script("BEGIN{OFS=\",\"} {$(NF+2)=5; print NF \":\" $0}")
216 .stdin("a b\n")
217 .expectLines("4:a,b,,5")
218 .runAndAssert();
219 }
220
221 @Test
222 public void spec17MissingActionPrintsRecord() throws Exception {
223 AwkTestSupport
224 .awkTest("17. Missing action prints record")
225 .script("1")
226 .stdin("x\n")
227 .expectLines("x")
228 .runAndAssert();
229 }
230
231 @Test
232 public void spec18RegexPatternMatchesRecords() throws Exception {
233 AwkTestSupport
234 .awkTest("18. Regex pattern matches records")
235 .script("/ar/")
236 .stdin("foo\nbar\n")
237 .expectLines("bar")
238 .runAndAssert();
239 }
240
241 @Test
242 public void spec19PatternOrderEvaluation() throws Exception {
243 AwkTestSupport
244 .awkTest("19. Pattern order evaluation")
245 .script("{flag=1} flag==1 {print \"seen\"}")
246 .stdin("x\n")
247 .expectLines("seen")
248 .runAndAssert();
249 }
250
251 @Test
252 public void spec20RangePatternWithinFile() throws Exception {
253 AwkTestSupport
254 .awkTest("20. Range pattern within file")
255 .script("/b/,/d/")
256 .stdin("a\nb\nc\nd\ne\n")
257 .expectLines("b", "c", "d")
258 .runAndAssert();
259 }
260
261 @Test
262 public void spec21RangePatternRepeats() throws Exception {
263 AwkTestSupport
264 .awkTest("21. Range pattern repeats")
265 .script("/start/,/end/")
266 .stdin("start\nx\nend\nx\nend\n")
267 .expectLines("start", "x", "end")
268 .runAndAssert();
269 }
270
271 @Test
272 public void spec22UnanchoredRegexMatchesSubstring() throws Exception {
273 AwkTestSupport
274 .awkTest("22. Unanchored regex matches substring")
275 .script("$0 ~ /b/")
276 .stdin("abc\n")
277 .expectLines("abc")
278 .runAndAssert();
279 }
280
281 @Test
282 public void spec23AnchoredRegex() throws Exception {
283 AwkTestSupport
284 .awkTest("23. Anchored regex")
285 .script("$0 ~ /^abc$/")
286 .stdin("abc\nabcx\n")
287 .expectLines("abc")
288 .runAndAssert();
289 }
290
291 @Test
292 public void spec24LiteralSlashInRegex() throws Exception {
293 AwkTestSupport
294 .awkTest("24. Literal slash in regex")
295 .script("$0 ~ /a\\/b/")
296 .stdin("a/b\n")
297 .expectLines("a/b")
298 .runAndAssert();
299 }
300
301 @Test
302 public void spec25RegexFromVariable() throws Exception {
303 AwkTestSupport
304 .awkTest("25. Regex from variable")
305 .script("BEGIN{re=\"a\\/b\"} $0 ~ re {print $0}")
306 .stdin("path a/b\n")
307 .expectLines("path a/b")
308 .runAndAssert();
309 }
310
311 @Test
312 public void spec26RegexStandalonePattern() throws Exception {
313 AwkTestSupport
314 .awkTest("26. Regex standalone pattern")
315 .script("/A/")
316 .stdin("xxAyy\n")
317 .expectLines("xxAyy")
318 .runAndAssert();
319 }
320
321 @Test
322 public void spec27MultipleBeginOrder() throws Exception {
323 AwkTestSupport
324 .awkTest("27. Multiple BEGIN order")
325 .script("BEGIN{print \"1\"} BEGIN{print \"2\"}")
326 .expectLines("1", "2")
327 .runAndAssert();
328 }
329
330 @Test
331 public void spec28MultipleEndOrder() throws Exception {
332 AwkTestSupport
333 .awkTest("28. Multiple END order")
334 .script("END{print \"E1\"} END{print \"E2\"}")
335 .stdin("x\ny\n")
336 .expectLines("E1", "E2")
337 .runAndAssert();
338 }
339
340 @Test
341 public void spec29GetlineInBeginConsumesRecord() throws Exception {
342 AwkTestSupport
343 .awkTest("29. getline in BEGIN consumes record")
344 .script("BEGIN{getline; print \"got:\" $0} {print \"line:\" $0}")
345 .stdin("L1\nL2\n")
346 .expectLines("got:L1", "line:L2")
347 .runAndAssert();
348 }
349
350 @Test
351 public void spec30FilenameVisibility() throws Exception {
352 AwkTestSupport
353 .awkTest("30. FILENAME visibility")
354 .script("BEGIN{print (FILENAME==\"\"?\"undef\":\"bad\")} {last=FILENAME} END{print last}")
355 .file("A", "a\n")
356 .file("B", "b\n")
357 .operand("{{A}}", "{{B}}")
358 .expectLines("undef", "{{B}}")
359 .runAndAssert();
360 }
361
362 @Test
363 public void spec31NrVsFnr() throws Exception {
364 AwkTestSupport
365 .awkTest("31. NR vs FNR")
366 .script("{print FILENAME \":\" FNR \":\" NR}")
367 .file("A", "x\ny\n")
368 .file("B", "z\n")
369 .operand("{{A}}", "{{B}}")
370 .expectLines("{{A}}:1:1", "{{A}}:2:2", "{{B}}:1:3")
371 .runAndAssert();
372 }
373
374 @Test
375 public void spec32ArgvManipulationSkipsFile() throws Exception {
376 AwkTestSupport
377 .awkTest("32. ARGV manipulation skips file")
378 .script("BEGIN{ARGV[1]=\"\"} {print FILENAME \":\" $0}")
379 .file("A", "a\n")
380 .file("B", "b\n")
381 .operand("{{A}}", "{{B}}")
382 .expectLines("{{B}}:b")
383 .runAndAssert();
384 }
385
386 @Test
387 public void spec33OfmtVsConvfmt() throws Exception {
388 AwkTestSupport
389 .awkTest("33. OFMT vs CONVFMT")
390 .script("BEGIN{OFMT=\"%.2f\"; CONVFMT=\"%.3f\"; x=1.2345; print x; s=x \"\"; print s}")
391 .expectLines("1.23", "1.24")
392 .runAndAssert();
393 }
394
395 @Test
396 public void spec34IntegersStringifyWithPercentD() throws Exception {
397 AwkTestSupport
398 .awkTest("34. Integers stringify with %d")
399 .script("BEGIN{CONVFMT=\"%.3f\"; x=12; s=x \"\"; print s}")
400 .expectLines("12")
401 .runAndAssert();
402 }
403
404 @Test
405 public void spec35NumericVsStringComparison() throws Exception {
406 AwkTestSupport
407 .awkTest("35. Numeric vs string comparison")
408 .script("{print ($0<10)?\"Y\":\"N\"}")
409 .stdin("2\n2a\n")
410 .expectLines("Y", "N")
411 .runAndAssert();
412 }
413
414 @Test
415 public void spec36ExponentiationRightAssociative() throws Exception {
416 AwkTestSupport
417 .awkTest("36. Exponentiation is right-associative")
418 .script("BEGIN{print 2^3^2}")
419 .expectLines("512")
420 .runAndAssert();
421 }
422
423 @Test
424 public void spec37ModulusUsesFmodSemantics() throws Exception {
425 AwkTestSupport
426 .awkTest("37. Modulus uses fmod semantics")
427 .script("BEGIN{print (-5)%2}")
428 .expectLines("-1")
429 .runAndAssert();
430 }
431
432 @Test
433 public void spec38ConcatenationPrecedence() throws Exception {
434 AwkTestSupport
435 .awkTest("38. Concatenation precedence")
436 .script("BEGIN{print 1 2+3}")
437 .expectLines("15")
438 .runAndAssert();
439 }
440
441 @Test
442 public void spec39TernaryRightAssociativity() throws Exception {
443 AwkTestSupport
444 .awkTest("39. Ternary right associativity")
445 .script("BEGIN{print (0?1:0?2:3)}")
446 .expectLines("3")
447 .runAndAssert();
448 }
449
450 @Test
451 public void spec40PreVsPostIncrement() throws Exception {
452 AwkTestSupport
453 .awkTest("40. Pre vs post increment")
454 .script("BEGIN{i=0; print i++; print i; j=0; print ++j; print j}")
455 .expectLines("0", "1", "1", "1")
456 .runAndAssert();
457 }
458
459 @Test
460 public void spec41FieldExpressionIndex() throws Exception {
461 AwkTestSupport
462 .awkTest("41. Field expression index")
463 .script("{i=2; print $(i)}")
464 .stdin("a b c\n")
465 .expectLines("b")
466 .runAndAssert();
467 }
468
469 @Test
470 public void spec42PrintWithEmptyExprList() throws Exception {
471 AwkTestSupport
472 .awkTest("42. Print with empty expr list")
473 .script("{print; print $0}")
474 .stdin("hello\n")
475 .expectLines("hello", "hello")
476 .runAndAssert();
477 }
478
479 @Test
480 public void spec43OfsAndOrs() throws Exception {
481 AwkTestSupport
482 .awkTest("43. OFS and ORS")
483 .script("BEGIN{OFS=\",\"; ORS=\"|\"} {print $1,$2; print $2,$1}")
484 .stdin("a b\n")
485 .expect("a,b|b,a|")
486 .runAndAssert();
487 }
488
489 @Test
490 public void spec44PrintfWidthAndPrecision() throws Exception {
491 AwkTestSupport
492 .awkTest("44. printf width and precision")
493 .script("BEGIN{printf \"%.3f\\n\", 1.23456; printf \"%5s\\n\", \"x\"}")
494 .expectLines("1.235", " x")
495 .runAndAssert();
496 }
497
498 @Test
499 public void spec45PrintfDoesNotUnescapeVariableFormat() throws Exception {
500 AwkTestSupport
501 .awkTest("45. printf does not unescape variable format")
502 .script("BEGIN{fmt=\"\\\\n\"; printf fmt; printf \"\\n\"}")
503 .expect("\\n\n")
504 .runAndAssert();
505 }
506
507 @Test
508 public void spec46WriteToFileAndClose() throws Exception {
509 AwkTestSupport
510 .awkTest("46. Write to file and close")
511 .path("tOut")
512 .script(
513 "BEGIN{f=\"{{tOut}}\"; print \"X\" > f; rc=close(f); print rc; while ((getline line < f)>0) print \"line: \" line \".\"; close(f)}")
514
515 .expect("0\nline: X.\n")
516 .runAndAssert();
517 }
518
519 @Test
520 public void spec47AppendWithRedirect() throws Exception {
521 AwkTestSupport
522 .awkTest("47. Append with redirect")
523 .path("tAppend")
524 .script(
525 "BEGIN{f=\"{{tAppend}}\"; print \"A\" >> f; print \"B\" >> f; close(f); while ((getline line < f)>0) print line; close(f)}")
526 .expectLines("A", "B")
527 .runAndAssert();
528 }
529
530 @Test
531 public void spec48PipeToCommandProducesOutput() throws Exception {
532 AwkTestSupport
533 .awkTest("48. Pipe to command produces output")
534 .script("{print $0 | \"sed s/a/A/\"} END{close(\"sed s/a/A/\")}")
535 .stdin("a\nb\n")
536 .posixOnly()
537 .expectLines("A", "b")
538 .runAndAssert();
539 }
540
541 @Test
542 public void spec49CommandPipeGetline() throws Exception {
543 AwkTestSupport
544 .awkTest("49. Command pipe getline")
545 .script("BEGIN{cmd=\"printf abc\\n\"; n=(cmd | getline x); print n \":\" x; close(cmd)}")
546 .posixOnly()
547 .expectLines("1:abc")
548 .runAndAssert();
549 }
550
551 @Test
552 public void spec50GetlineFromFileReturnsCounts() throws Exception {
553 AwkTestSupport
554 .awkTest("50. getline from file returns counts")
555 .file("fileX", "L1\nL2\n")
556 .script("BEGIN{f=\"{{fileX}}\"; n=0; while ((rc=(getline ln < f))>0){n++} print n \":\" rc; close(f)}")
557 .expectLines("2:0")
558 .runAndAssert();
559 }
560
561 @Test
562 public void spec51SystemExitStatus() throws Exception {
563 AwkTestSupport
564 .awkTest("51. system() exit status")
565 .script("BEGIN{print system(\"sh -c true\"); print (system(\"sh -c false\")!=0?\"NZ\":\"Z\")}")
566 .posixOnly()
567 .expectLines("0", "NZ")
568 .runAndAssert();
569 }
570
571 @Test
572 public void spec52NextSkipsRemainingRules() throws Exception {
573 AwkTestSupport
574 .awkTest("52. next skips remaining rules")
575 .script("{print \"A:\" $0; next; print \"B:\" $0}")
576 .stdin("a\nb\n")
577 .expectLines("A:a", "A:b")
578 .runAndAssert();
579 }
580
581 @Test
582 public void spec53EmulateNextfileSkipsToNextFile() throws Exception {
583 AwkTestSupport
584 .awkTest("53. emulate nextfile skips to next file")
585 .script(
586 "FNR==1{print $0; fname=FILENAME; while (getline > 0) { if (FILENAME!=fname) {print $0; break} } next} {print \"NEVER\"}")
587 .file("A", "a1\na2\n")
588 .file("B", "b1\n")
589 .operand("{{A}}", "{{B}}")
590 .expectLines("a1", "b1")
591 .runAndAssert();
592 }
593
594 @Test
595 public void spec54ExitStillRunsEnd() throws Exception {
596 AwkTestSupport
597 .awkTest("54. exit still runs END")
598 .script("{print; exit} END{print \"E\"}")
599 .stdin("x\ny\n")
600 .expectLines("x", "E")
601 .runAndAssert();
602 }
603
604 @Test
605 public void spec55BeginExitCode() throws Exception {
606 AwkTestSupport
607 .awkTest("55. BEGIN exit code")
608 .script("BEGIN{exit 3}")
609 .expect("")
610 .expectExit(3)
611 .runAndAssert();
612 }
613
614 @Test
615 public void spec56LengthDefaultArgument() throws Exception {
616 AwkTestSupport
617 .awkTest("56. length() default argument")
618 .script("{print length()}")
619 .stdin("abcd\n")
620 .expectLines("4")
621 .runAndAssert();
622 }
623
624 @Test
625 public void spec57IndexFunction() throws Exception {
626 AwkTestSupport
627 .awkTest("57. index function")
628 .script("BEGIN{print index(\"banana\",\"na\"); print index(\"banana\",\"x\")}")
629 .expectLines("3", "0")
630 .runAndAssert();
631 }
632
633 @Test
634 public void spec58SubstrVariations() throws Exception {
635 AwkTestSupport
636 .awkTest("58. substr variations")
637 .script("BEGIN{print substr(\"hello\",2,3); print substr(\"hello\",4)}")
638 .expectLines("ell", "lo")
639 .runAndAssert();
640 }
641
642 @Test
643 public void spec59MatchUpdatesRstartAndRlength() throws Exception {
644 AwkTestSupport
645 .awkTest("59. match updates RSTART and RLENGTH")
646 .script("BEGIN{print match(\"abc\",\"abc\"), RSTART, RLENGTH; print match(\"xyz\",\"a\"), RSTART, RLENGTH}")
647 .expectLines("1 1 3", "0 0 -1")
648 .runAndAssert();
649 }
650
651 @Test
652 public void spec60SubReplacesFirstOccurrence() throws Exception {
653 AwkTestSupport
654 .awkTest("60. sub replaces first occurrence")
655 .script("BEGIN{s=\"foo\"; n=sub(/f/, \"X\", s); print n \":\" s}")
656 .expectLines("1:Xoo")
657 .runAndAssert();
658 }
659
660 @Test
661 public void spec61GsubEscapesAmpersand() throws Exception {
662 AwkTestSupport
663 .awkTest("61. gsub escapes ampersand")
664 .script("BEGIN{s=\"aba\"; n=gsub(/a/,\"\\\\&X\",s); print n \":\" s}")
665 .expectLines("2:&Xb&X")
666 .runAndAssert();
667 }
668
669 @Test
670 public void spec62SplitClearsArrayAndCounts() throws Exception {
671 AwkTestSupport
672 .awkTest("62. split clears array and counts")
673 .script("BEGIN{delete a; n=split(\"a::b:c\", a, \"[:]+\"); print n \":\" a[1] \":\" a[2] \":\" a[3]}")
674 .expectLines("3:a:b:c")
675 .runAndAssert();
676 }
677
678 @Test
679 public void spec63SprintfFormatting() throws Exception {
680 AwkTestSupport
681 .awkTest("63. sprintf formatting")
682 .script("BEGIN{print sprintf(\"<%6.2f>\", 1.234)}")
683 .expectLines("< 1.23>")
684 .runAndAssert();
685 }
686
687 @Test
688 public void spec64IntTruncatesTowardZero() throws Exception {
689 AwkTestSupport
690 .awkTest("64. int truncates toward zero")
691 .script("BEGIN{print int(-1.7)}")
692 .expectLines("-1")
693 .runAndAssert();
694 }
695
696 @Test
697 public void spec65SrandProducesRepeatableSequence() throws Exception {
698 AwkTestSupport
699 .awkTest("65. srand produces repeatable sequence")
700 .script("BEGIN{srand(1); r1=rand(); srand(1); r2=rand(); print (r1==r2)?1:0}")
701 .expectLines("1")
702 .runAndAssert();
703 }
704
705 @Test
706 public void spec66SqrtPositive() throws Exception {
707 AwkTestSupport
708 .awkTest("66. sqrt positive")
709 .script("BEGIN{printf \"%.5f\\n\", sqrt(9)}")
710 .expectLines("3.00000")
711 .runAndAssert();
712 }
713
714 @Test
715 public void spec67InOperatorForArrays() throws Exception {
716 AwkTestSupport
717 .awkTest("67. in operator for arrays")
718 .script("BEGIN{print ((1 in a)?1:0); a[1]=0; print ((1 in a)?1:0)}")
719 .expectLines("0", "1")
720 .runAndAssert();
721 }
722
723 @Test
724 public void spec68MultidimensionalArraysViaSubsep() throws Exception {
725 AwkTestSupport
726 .awkTest("68. Multidimensional arrays via SUBSEP")
727 .script("BEGIN{a[1,2]=42; print a[1 SUBSEP 2]}")
728 .expectLines("42")
729 .runAndAssert();
730 }
731
732 @Test
733 public void spec69DeleteElementAndArray() throws Exception {
734 AwkTestSupport
735 .awkTest("69. delete element and array")
736 .script(
737 "BEGIN{a[1]=10; a[2]=20; delete a[1]; c=0; for(i in a)c++; print c; delete a; c=0; for(i in a)c++; print c}")
738 .expectLines("1", "0")
739 .runAndAssert();
740 }
741
742 @Test
743 public void spec70SplitYieldsNumericStrings() throws Exception {
744 AwkTestSupport
745 .awkTest("70. split yields numeric strings")
746 .script("BEGIN{n=split(\"10 20\",a,\" \" ); print (a[1]+0)+(a[2]+0)}")
747 .expectLines("30")
748 .runAndAssert();
749 }
750
751 @Test
752 public void spec71ScalarsPassedByValue() throws Exception {
753 AwkTestSupport
754 .awkTest("71. Scalars passed by value")
755 .script("function f(x){x=5} BEGIN{y=3; f(y); print y}")
756 .expectLines("3")
757 .runAndAssert();
758 }
759
760 @Test
761 public void spec72ArraysPassedByReference() throws Exception {
762 AwkTestSupport
763 .awkTest("72. Arrays passed by reference")
764 .script("function g(arr){arr[1]=\"X\"} BEGIN{a[1]=\"A\"; g(a); print a[1]}")
765 .expectLines("X")
766 .runAndAssert();
767 }
768
769 @Test
770 public void spec73MissingActualArgsDefaultToEmpty() throws Exception {
771 AwkTestSupport
772 .awkTest("73. Missing actual args default to empty")
773 .script("function f(u,v){print (u==\"\"?\"E\":u) \":\" (v==\"\"?\"E\":v)} BEGIN{f(1)}")
774 .expectLines("1:E")
775 .runAndAssert();
776 }
777
778 @Test
779 public void spec74FunctionCallRequiresNoWhitespace() throws Exception {
780 AwkTestSupport
781 .awkTest("74. Function call requires no whitespace")
782 .script("function f(x){return x} BEGIN{print f(7)}")
783 .expectLines("7")
784 .runAndAssert();
785 }
786
787 @Test
788 public void spec75RecursiveFunction() throws Exception {
789 AwkTestSupport
790 .awkTest("75. Recursive function")
791 .script("function fact(n){return n? n*fact(n-1):1} BEGIN{print fact(5)}")
792 .expectLines("120")
793 .runAndAssert();
794 }
795
796 @Test
797 public void spec76BareGetlineUpdatesRecordState() throws Exception {
798 AwkTestSupport
799 .awkTest("76. Bare getline updates record state")
800 .file("A", "a\nb\n")
801 .script("BEGIN{print NR \":\" FNR} {if (NR==1){getline; print $0 \":\" NF \":\" NR \":\" FNR; exit}}")
802 .operand("{{A}}")
803 .expectLines("0:0", "b:1:2:2")
804 .runAndAssert();
805 }
806
807 @Test
808 public void spec77GetlineVarLeavesZeroUnchanged() throws Exception {
809 AwkTestSupport
810 .awkTest("77. getline var leaves $0 unchanged")
811 .file("A", "a\nb\n")
812 .script("{ if (FNR==1) { getline line; print line \":\" $0 \":\" NF \":\" NR \":\" FNR; exit } }")
813 .operand("{{A}}")
814 .expectLines("b:a:1:2:2")
815 .runAndAssert();
816 }
817
818 @Test
819 public void spec78GetlineFromNamedFileAndClose() throws Exception {
820 AwkTestSupport
821 .awkTest("78. getline from named file and close")
822 .file("f1", "L1\nL2\n")
823 .script("BEGIN{f=\"{{f1}}\"; getline x < f; getline y < f; print x \"-\" y; print (close(f)==0)}")
824 .expectLines("L1-L2", "1")
825 .runAndAssert();
826 }
827
828 @Test
829 public void spec79BeginNrFnrZeroAndGetlineSetsNf() throws Exception {
830 AwkTestSupport
831 .awkTest("79. BEGIN NR/FNR zero and getline sets NF")
832 .script("BEGIN{print NR \":\" FNR; getline; print NF \":\" $0; exit}")
833 .stdin("x\n")
834 .expectLines("0:0", "1:x")
835 .runAndAssert();
836 }
837
838 @Test
839 public void spec80EndSeesTotalNr() throws Exception {
840 AwkTestSupport
841 .awkTest("80. END sees total NR")
842 .script("END{print NR}")
843 .stdin("a\nb\nc\n")
844 .expectLines("3")
845 .runAndAssert();
846 }
847
848 @Test
849 public void spec81StringComparisonInCLocale() throws Exception {
850 AwkTestSupport
851 .awkTest("81. String comparison in C locale")
852 .script("BEGIN{print (\"abc\"<\"abd\")?\"Y\":\"N\"}")
853 .expectLines("Y")
854 .runAndAssert();
855 }
856
857 @Test
858 public void spec82NumericComparisonWithNumericStrings() throws Exception {
859 AwkTestSupport
860 .awkTest("82. Numeric comparison with numeric strings")
861 .script("BEGIN{print (10<\"2\")?\"Y\":\"N\"; print (10<(\" 2\"))?\"Y\":\"N\"}")
862 .expectLines("N", "N")
863 .runAndAssert();
864 }
865
866 @Test
867 public void spec83AssignmentsInArgv() throws Exception {
868 AwkTestSupport
869 .awkTest("83. Assignments in ARGV")
870 .script("{print X \":\" $0}")
871 .file("A", "a\n")
872 .operand("X=Q", "{{A}}")
873 .expectLines("Q:a")
874 .runAndAssert();
875 }
876
877 @Test
878 public void spec84AppendFileViaArgvInBegin() throws Exception {
879 AwkTestSupport
880 .awkTest("84. Append file via ARGV in BEGIN")
881 .script("BEGIN{ARGC=ARGC+1; ARGV[ARGC-1]=\"{{A}}\"} {print $0}")
882 .file("A", "a\n")
883 .operand("{{A}}")
884 .expectLines("a", "a")
885 .runAndAssert();
886 }
887
888 @Test
889 public void spec85SemicolonStatementSeparators() throws Exception {
890 AwkTestSupport
891 .awkTest("85. Semicolon statement separators")
892 .script("{a=1; b=2; print a+b}")
893 .stdin("x\n")
894 .expectLines("3")
895 .runAndAssert();
896 }
897
898 @Test
899 public void spec86ForInIterationCount() throws Exception {
900 AwkTestSupport
901 .awkTest("86. for-in iteration count")
902 .script("BEGIN{a[\"x\"]=1; a[\"y\"]=2; c=0; for (i in a) c++; print c}")
903 .expectLines("2")
904 .runAndAssert();
905 }
906
907 @Test
908 public void spec87RebuildZeroWithCustomOfs() throws Exception {
909 AwkTestSupport
910 .awkTest("87. Rebuild $0 with custom OFS")
911 .script("BEGIN{OFS=\"|\"} {$2=\"\"; print $0 \":\" NF}")
912 .stdin("a b\n")
913 .expectLines("a|:2")
914 .runAndAssert();
915 }
916
917 @Test
918 public void spec88SplitWithLiteralSpaceSeparator() throws Exception {
919 AwkTestSupport
920 .awkTest("88. split with literal space separator")
921 .script("BEGIN{n=split(\" a\\t b c \", a, \" \" ); print n \":\" a[1] \":\" a[2] \":\" a[3]}")
922 .expectLines("3:a:b:c")
923 .runAndAssert();
924 }
925
926 @Test
927 public void spec89FsAsClassRepetition() throws Exception {
928 AwkTestSupport
929 .awkTest("89. FS as class repetition")
930 .script("BEGIN{FS=\"[ ,:]+\"}{print NF \":\" $1 \":\" $2}")
931 .stdin("a , , : :b\n")
932 .expectLines("2:a:b")
933 .runAndAssert();
934 }
935
936 @Test
937 public void spec90RsEmptyIgnoresLeadingBlanks() throws Exception {
938 AwkTestSupport
939 .awkTest("90. RS empty ignores leading blanks")
940 .script(
941 "BEGIN{RS=\"\"}{gsub(\"(\\\\n)+\",\" \",$0); sub(\"^ +\",\"\",$0); sub(\" +$\",\"\",$0); print \"REC-\" NR \":\" $0}")
942 .stdin("\n\npara1\n\n\npara2\n\n")
943 .expectLines("REC-1:para1 para2")
944 .runAndAssert();
945 }
946
947 @Test
948 public void spec91RangeResetsPerFile() throws Exception {
949 AwkTestSupport
950 .awkTest("91. Range resets per file")
951 .script("/1/,/2/ {print FILENAME \":\" $0}")
952 .file("A", "1\nX\n2\n")
953 .file("B", "1\n2\n")
954 .operand("{{A}}", "{{B}}")
955 .expectLines("{{A}}:1", "{{A}}:X", "{{A}}:2", "{{B}}:1", "{{B}}:2")
956 .runAndAssert();
957 }
958
959 @Test
960 public void spec92EnvironExposesEnvironmentVariable() throws Exception {
961 AwkTestSupport
962 .awkTest("92. ENVIRON exposes environment variable")
963 .script("BEGIN{print ENVIRON[\"PATH\"]}")
964 .expectLines(System.getenv().getOrDefault("PATH", ""))
965 .runAndAssert();
966 }
967
968 @Test
969 public void spec93MatchUsesRegexVariable() throws Exception {
970 AwkTestSupport
971 .awkTest("93. match uses regex variable")
972 .script("BEGIN{re=\"fo+\"; print match(\"foo\",re)}")
973 .expectLines("1")
974 .runAndAssert();
975 }
976
977 @Test
978 public void spec94ActionOnlyPrintsRecords() throws Exception {
979 AwkTestSupport
980 .awkTest("94. Action-only prints records")
981 .script("{print NR \":\" $0}")
982 .stdin("x\ny\n")
983 .expectLines("1:x", "2:y")
984 .runAndAssert();
985 }
986
987 @Test
988 public void spec95PatternOnlyExpression() throws Exception {
989 AwkTestSupport
990 .awkTest("95. Pattern-only expression")
991 .script("($0+0) {print NR \":T\"}")
992 .stdin("1\n0\n")
993 .expectLines("1:T")
994 .runAndAssert();
995 }
996 }