Add toolchain_test.py to naclbuild.py
[nacl-build.git] / gccwrapper_test.py
blob94be3797d2a30eb864ced1b6061de24308edec7a
2 import os
3 import shutil
4 import subprocess
5 import tempfile
6 import unittest
9 # From http://lackingrhoticity.blogspot.com/2008/11/tempdirtestcase-python-unittest-helper.html
10 class TempDirTestCase(unittest.TestCase):
12 def setUp(self):
13 self._on_teardown = []
15 def make_temp_dir(self):
16 temp_dir = tempfile.mkdtemp(prefix="tmp-%s-" % self.__class__.__name__)
17 def tear_down():
18 shutil.rmtree(temp_dir)
19 self._on_teardown.append(tear_down)
20 return temp_dir
22 def tearDown(self):
23 for func in reversed(self._on_teardown):
24 func()
27 def write_file(filename, data):
28 fh = open(filename, "w")
29 try:
30 fh.write(data)
31 finally:
32 fh.close()
35 example_prog = """
36 #include <stdio.h>
37 int main() {
38 printf("%s", ""); /* Tests making a function call */
39 return 0;
41 """
44 class GccWrapperTest(TempDirTestCase):
46 def test_default_output_file_for_linking(self):
47 temp_dir = self.make_temp_dir()
48 write_file(os.path.join(temp_dir, "foo.c"), example_prog)
49 subprocess.check_call(["nacl-glibc-gcc", "-Wall", "foo.c"],
50 cwd=temp_dir)
51 self.assertEquals(sorted(os.listdir(temp_dir)), ["a.out", "foo.c"])
52 # Nops should have been written. Executable should be runnable.
53 subprocess.check_call([os.path.join(temp_dir, "a.out")])
55 def test_default_output_file_for_c(self):
56 temp_dir = self.make_temp_dir()
57 write_file(os.path.join(temp_dir, "foo.c"), example_prog)
58 subprocess.check_call(["nacl-glibc-gcc", "-Wall", "-c", "foo.c"],
59 cwd=temp_dir)
60 subprocess.check_call(["gcc", "foo.o", "-o", "foo"], cwd=temp_dir)
61 # Nops should have been written. Executable should be runnable.
62 subprocess.check_call([os.path.join(temp_dir, "foo")])
64 def test_explicit_output_file(self):
65 temp_dir = self.make_temp_dir()
66 write_file(os.path.join(temp_dir, "foo.c"), example_prog)
67 subprocess.check_call(["nacl-glibc-gcc", "-Wall", "foo.c", "-o", "foo"],
68 cwd=temp_dir)
69 # Nops should have been written. Executable should be runnable.
70 subprocess.check_call([os.path.join(temp_dir, "foo")])
72 def test_building_against_installed_libraries(self):
73 # Assumes libreadline5-dev is installed.
74 temp_dir = self.make_temp_dir()
75 write_file(os.path.join(temp_dir, "foo.c"), """
76 #include <readline/readline.h>
77 int main()
79 return 0;
81 """)
82 subprocess.check_call(
83 ["nacl-glibc-gcc", "-Wall", "foo.c", "-lreadline", "-o", "foo"],
84 cwd=temp_dir)
85 subprocess.check_call([os.path.join(temp_dir, "foo")])
88 class GlibcTest(TempDirTestCase):
90 def test_linking_with_libpthread(self):
91 # Just tests that libpthread initialises OK.
92 temp_dir = self.make_temp_dir()
93 write_file(os.path.join(temp_dir, "foo.c"), example_prog)
94 subprocess.check_call(
95 ["nacl-glibc-gcc", "-Wall", "foo.c", "-lpthread", "-o", "foo"],
96 cwd=temp_dir)
97 subprocess.check_call([os.path.join(temp_dir, "foo")])
99 def test_linking_with_dubious_options(self):
100 # Python links _sqlite.so with -L/usr/lib which causes the
101 # linker to drag in the static /usr/lib/libc.a.
102 temp_dir = self.make_temp_dir()
103 write_file(os.path.join(temp_dir, "foo.c"), example_prog)
104 subprocess.check_call(
105 ["nacl-glibc-gcc", "-Wall", "foo.c", "-lpthread",
106 "-L/usr/lib", "-o", "foo"],
107 cwd=temp_dir)
108 subprocess.check_call([os.path.join(temp_dir, "foo")])
109 # TODO: Validate resulting code. Otherwise broken output is
110 # noisy but doesn't signal failure.
112 def _check_fstat(self, suffix):
113 temp_dir = self.make_temp_dir()
114 write_file(os.path.join(temp_dir, "test.c"), r"""
115 #define _GNU_SOURCE
116 #include <fcntl.h>
117 #include <stddef.h>
118 #include <stdio.h>
119 #include <string.h>
120 #include <sys/stat.h>
121 int main()
123 struct stat%(suffix)s st;
124 int fd = open("test", O_RDONLY);
125 if(fd < 0) {
126 perror("open");
127 return 1;
129 memset(&st, 0xee, sizeof(st));
130 if(fstat%(suffix)s(fd, &st) < 0) {
131 perror("fstat");
132 return 1;
135 #define FIELD(name) printf("('%%s', %%li),\n", #name, (long) st.name)
136 FIELD(st_dev);
137 FIELD(st_ino);
138 FIELD(st_mode);
139 FIELD(st_nlink);
140 FIELD(st_uid);
141 FIELD(st_gid);
142 FIELD(st_rdev);
143 FIELD(st_size);
144 FIELD(st_blksize);
145 FIELD(st_blocks);
146 FIELD(st_atime);
147 FIELD(st_mtime);
148 FIELD(st_ctime);
149 return 0;
151 """ % {"suffix": suffix})
152 subprocess.check_call(["nacl-glibc-gcc", "test.c", "-o", "test"], cwd=temp_dir)
153 subprocess.check_call(["ncrewrite", "test"], cwd=temp_dir)
154 args = ["sel_ldr",
155 "-d", os.path.join(os.getcwd(), "install-stubout/lib/ld-linux.so.2"),
156 "--", "--library-path", os.path.join(os.getcwd(), "install-stubout/lib"),
157 "./test"]
158 proc = subprocess.Popen(args, stdout=subprocess.PIPE,
159 stderr=open(os.devnull, "w"),
160 cwd=temp_dir)
161 stdout = proc.communicate()[0]
162 self.assertEquals(proc.wait(), 0)
163 fields = dict(eval("[%s]" % stdout, {}))
164 real_stat = os.stat(os.path.join(temp_dir, "test"))
165 # Some of these values are dummy values filled out by NaCl.
166 self.assertEquals(fields["st_dev"], 0)
167 # As a hack, a new st_ino is returned each time by NaCl but we
168 # expect it to be small but non-zero.
169 assert 0 < fields["st_ino"] < 100, fields["st_ino"]
170 # NaCl clears the "group" and "other" permission bits.
171 self.assertEquals("%o" % fields["st_mode"],
172 "%o" % (real_stat.st_mode & ~0077))
173 self.assertEquals(fields["st_nlink"], real_stat.st_nlink)
174 self.assertEquals(fields["st_uid"], -1)
175 self.assertEquals(fields["st_gid"], -1)
176 self.assertEquals(fields["st_rdev"], 0)
177 self.assertEquals(fields["st_size"], real_stat.st_size)
178 self.assertEquals(fields["st_blksize"], 0)
179 self.assertEquals(fields["st_blocks"], 0)
180 self.assertEquals(fields["st_atime"], real_stat.st_atime)
181 self.assertEquals(fields["st_mtime"], real_stat.st_mtime)
182 self.assertEquals(fields["st_ctime"], real_stat.st_ctime)
184 def test_fstat(self):
185 self._check_fstat(suffix="")
187 def test_fstat64(self):
188 self._check_fstat(suffix="64")
191 if __name__ == "__main__":
192 unittest.main()