1import os
2
3import infra.basetest
4
5
6class TestGawk(infra.basetest.BRTest):
7    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
8        """
9        BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
10        BR2_PACKAGE_GAWK=y
11        BR2_TARGET_ROOTFS_CPIO=y
12        # BR2_TARGET_ROOTFS_TAR is not set
13        """
14
15    def basic_gawk_tests(self):
16        # Check the program can execute
17        self.assertRunOk("gawk --version")
18
19        # Check "awk" is "gawk": the Buildroot gawk package recipe is
20        # supposed to install the symbolic link.
21        output, exit_code = self.emulator.run("awk --version")
22        self.assertEqual(exit_code, 0)
23        self.assertTrue(output[0].startswith("GNU Awk"))
24
25        # Check "gawk" can return a specific exit code
26        code = 123
27        cmd = "gawk 'BEGIN { exit(" + str(code) + "); }'"
28        _, exit_code = self.emulator.run(cmd)
29        self.assertEqual(exit_code, code)
30
31        # Run a basic print program
32        test_string = "Hello Buildroot"
33        cmd = "gawk 'BEGIN {print \"" + test_string + "\"; }'"
34        output, exit_code = self.emulator.run(cmd)
35        self.assertEqual(exit_code, 0)
36        self.assertEqual(output[0], test_string)
37
38    def create_test_data(self):
39        # Create some test data
40        entries = ["one", "two", "three", "four"]
41        for entry in entries:
42            self.assertRunOk(f"echo {entry} >> data1.txt")
43
44    def add_line_numbers(self):
45        # Add line numbers with gawk
46        cmd = "gawk '{ print NR \"\\t\" $1; }' data1.txt > data2.txt"
47        self.assertRunOk(cmd)
48
49    def sum_column(self):
50        # Check the sum of the first column is 1+2+3+4 == 10
51        awk_prg = "BEGIN { SUM = 0; } { SUM = SUM + $1; } END { print SUM; }"
52        cmd = f"gawk '{awk_prg}' data2.txt"
53        output, exit_code = self.emulator.run(cmd)
54        self.assertEqual(exit_code, 0)
55        self.assertEqual(int(output[0]), 10)
56
57    def uppercase_column(self):
58        # Extract only column 2 and convert it to upper case
59        cmd = "gawk '{ print toupper($2); }' data2.txt > data3.txt"
60        self.assertRunOk(cmd)
61
62        # Prepare the same output using "data1.txt" and the "tr" command,
63        # for verification
64        cmd = "tr a-z A-Z < data1.txt > data3-tr.txt"
65        self.assertRunOk(cmd)
66
67        # "gawk" and "tr" output are expected to be the same
68        self.assertRunOk("cmp data3.txt data3-tr.txt")
69
70    def gawk_head(self):
71        # Show the first 2 lines of a file
72        cmd = "gawk 'NR <= 2 { print $0; }' data2.txt > data4.txt"
73        self.assertRunOk(cmd)
74
75        # Prepare the same output using the "head" command
76        cmd = "head -2 data2.txt > data4-head.txt"
77        self.assertRunOk(cmd)
78
79        # "gawk" and "tr" output are expected to be the same
80        self.assertRunOk("cmp data4.txt data4-head.txt")
81
82    def gawk_specific(self):
83        # Use PROCINFO, which is a gawk specific feature:
84        # https://www.gnu.org/software/gawk/manual/gawk.html#POSIX_002fGNU
85        awk_platform_prog = "BEGIN { print PROCINFO[\"platform\"]; }"
86        cmd = f"gawk '{awk_platform_prog}'"
87        output, exit_code = self.emulator.run(cmd)
88        self.assertEqual(exit_code, 0)
89        self.assertEqual(output[0], "posix")
90
91        # Using the same gawk feature when running in POSIX mode should not
92        # produce output.
93        cmd = f"gawk --posix '{awk_platform_prog}'"
94        output, exit_code = self.emulator.run(cmd)
95        self.assertEqual(exit_code, 0)
96        self.assertTrue(len(output) == 1 and len(output[0]) == 0)
97
98    def gawk_numeric(self):
99        value = 1234
100        squared_value = value * value
101        cmd = "gawk 'BEGIN { print sqrt(" + str(squared_value) + "); }'"
102        output, exit_code = self.emulator.run(cmd)
103        self.assertEqual(exit_code, 0)
104        self.assertEqual(int(output[0]), value)
105
106    def test_run(self):
107        cpio_file = os.path.join(self.builddir, "images", "rootfs.cpio")
108        self.emulator.boot(arch="armv5",
109                           kernel="builtin",
110                           options=["-initrd", cpio_file])
111        self.emulator.login()
112
113        self.basic_gawk_tests()
114        self.create_test_data()
115        self.add_line_numbers()
116        self.sum_column()
117        self.uppercase_column()
118        self.gawk_head()
119        self.gawk_specific()
120        self.gawk_numeric()
121