1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5from __future__ import absolute_import, print_function, unicode_literals
6
7from mozbuild.makeutil import (
8    Makefile,
9    read_dep_makefile,
10    Rule,
11    write_dep_makefile,
12)
13from mozunit import main
14import os
15from six import StringIO
16import unittest
17
18
19class TestMakefile(unittest.TestCase):
20    def test_rule(self):
21        out = StringIO()
22        rule = Rule()
23        rule.dump(out)
24        self.assertEqual(out.getvalue(), "")
25
26        out = StringIO()
27        rule.add_targets(["foo", "bar"])
28        rule.dump(out)
29        self.assertEqual(out.getvalue(), "foo bar:\n")
30
31        out = StringIO()
32        rule.add_targets(["baz"])
33        rule.add_dependencies(["qux", "hoge", "piyo"])
34        rule.dump(out)
35        self.assertEqual(out.getvalue(), "foo bar baz: qux hoge piyo\n")
36
37        out = StringIO()
38        rule = Rule(["foo", "bar"])
39        rule.add_dependencies(["baz"])
40        rule.add_commands(["echo $@"])
41        rule.add_commands(["$(BAZ) -o $@ $<", "$(TOUCH) $@"])
42        rule.dump(out)
43        self.assertEqual(
44            out.getvalue(),
45            "foo bar: baz\n"
46            + "\techo $@\n"
47            + "\t$(BAZ) -o $@ $<\n"
48            + "\t$(TOUCH) $@\n",
49        )
50
51        out = StringIO()
52        rule = Rule(["foo"])
53        rule.add_dependencies(["bar", "foo", "baz"])
54        rule.dump(out)
55        self.assertEqual(out.getvalue(), "foo: bar baz\n")
56
57        out = StringIO()
58        rule.add_targets(["bar"])
59        rule.dump(out)
60        self.assertEqual(out.getvalue(), "foo bar: baz\n")
61
62        out = StringIO()
63        rule.add_targets(["bar"])
64        rule.dump(out)
65        self.assertEqual(out.getvalue(), "foo bar: baz\n")
66
67        out = StringIO()
68        rule.add_dependencies(["bar"])
69        rule.dump(out)
70        self.assertEqual(out.getvalue(), "foo bar: baz\n")
71
72        out = StringIO()
73        rule.add_dependencies(["qux"])
74        rule.dump(out)
75        self.assertEqual(out.getvalue(), "foo bar: baz qux\n")
76
77        out = StringIO()
78        rule.add_dependencies(["qux"])
79        rule.dump(out)
80        self.assertEqual(out.getvalue(), "foo bar: baz qux\n")
81
82        out = StringIO()
83        rule.add_dependencies(["hoge", "hoge"])
84        rule.dump(out)
85        self.assertEqual(out.getvalue(), "foo bar: baz qux hoge\n")
86
87        out = StringIO()
88        rule.add_targets(["fuga", "fuga"])
89        rule.dump(out)
90        self.assertEqual(out.getvalue(), "foo bar fuga: baz qux hoge\n")
91
92    def test_makefile(self):
93        out = StringIO()
94        mk = Makefile()
95        rule = mk.create_rule(["foo"])
96        rule.add_dependencies(["bar", "baz", "qux"])
97        rule.add_commands(["echo foo"])
98        rule = mk.create_rule().add_targets(["bar", "baz"])
99        rule.add_dependencies(["hoge"])
100        rule.add_commands(["echo $@"])
101        mk.dump(out, removal_guard=False)
102        self.assertEqual(
103            out.getvalue(),
104            "foo: bar baz qux\n" + "\techo foo\n" + "bar baz: hoge\n" + "\techo $@\n",
105        )
106
107        out = StringIO()
108        mk.dump(out)
109        self.assertEqual(
110            out.getvalue(),
111            "foo: bar baz qux\n"
112            + "\techo foo\n"
113            + "bar baz: hoge\n"
114            + "\techo $@\n"
115            + "hoge qux:\n",
116        )
117
118    def test_statement(self):
119        out = StringIO()
120        mk = Makefile()
121        mk.create_rule(["foo"]).add_dependencies(["bar"]).add_commands(["echo foo"])
122        mk.add_statement("BAR = bar")
123        mk.create_rule(["$(BAR)"]).add_commands(["echo $@"])
124        mk.dump(out, removal_guard=False)
125        self.assertEqual(
126            out.getvalue(),
127            "foo: bar\n" + "\techo foo\n" + "BAR = bar\n" + "$(BAR):\n" + "\techo $@\n",
128        )
129
130    @unittest.skipIf(os.name != "nt", "Test only applicable on Windows.")
131    def test_path_normalization(self):
132        out = StringIO()
133        mk = Makefile()
134        rule = mk.create_rule(["c:\\foo"])
135        rule.add_dependencies(["c:\\bar", "c:\\baz\\qux"])
136        rule.add_commands(["echo c:\\foo"])
137        mk.dump(out)
138        self.assertEqual(
139            out.getvalue(),
140            "c:/foo: c:/bar c:/baz/qux\n" + "\techo c:\\foo\n" + "c:/bar c:/baz/qux:\n",
141        )
142
143    def test_read_dep_makefile(self):
144        input = StringIO(
145            os.path.abspath("foo")
146            + ": bar\n"
147            + "baz qux: \\ \n"
148            + "hoge \\\n"
149            + "piyo \\\n"
150            + "fuga\n"
151            + "fuga:\n"
152        )
153        result = list(read_dep_makefile(input))
154        self.assertEqual(len(result), 2)
155        self.assertEqual(
156            list(result[0].targets()), [os.path.abspath("foo").replace(os.sep, "/")]
157        )
158        self.assertEqual(list(result[0].dependencies()), ["bar"])
159        self.assertEqual(list(result[1].targets()), ["baz", "qux"])
160        self.assertEqual(list(result[1].dependencies()), ["hoge", "piyo", "fuga"])
161
162    def test_write_dep_makefile(self):
163        out = StringIO()
164        write_dep_makefile(out, "target", ["b", "c", "a"])
165        self.assertEqual(out.getvalue(), "target: b c a\n" + "a b c:\n")
166
167
168if __name__ == "__main__":
169    main()
170