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 StringIO import StringIO 8import os 9import sys 10import textwrap 11import unittest 12 13from mozunit import ( 14 main, 15 MockedOpen, 16) 17 18from mozbuild.configure import ( 19 ConfigureError, 20 ConfigureSandbox, 21) 22from mozbuild.util import exec_ 23from mozpack import path as mozpath 24 25from buildconfig import topsrcdir 26from common import ( 27 ConfigureTestSandbox, 28 ensure_exe_extension, 29 fake_short_path, 30) 31 32 33class TestChecksConfigure(unittest.TestCase): 34 def test_checking(self): 35 out = StringIO() 36 sandbox = ConfigureSandbox({}, stdout=out, stderr=out) 37 base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') 38 sandbox.include_file(os.path.join(base_dir, 'checks.configure')) 39 40 exec_(textwrap.dedent(''' 41 @checking('for a thing') 42 def foo(value): 43 return value 44 '''), sandbox) 45 46 foo = sandbox['foo'] 47 48 foo(True) 49 self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') 50 51 out.truncate(0) 52 foo(False) 53 self.assertEqual(out.getvalue(), 'checking for a thing... no\n') 54 55 out.truncate(0) 56 foo(42) 57 self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') 58 59 out.truncate(0) 60 foo('foo') 61 self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') 62 63 out.truncate(0) 64 data = ['foo', 'bar'] 65 foo(data) 66 self.assertEqual(out.getvalue(), 'checking for a thing... %r\n' % data) 67 68 # When the function given to checking does nothing interesting, the 69 # behavior is not altered 70 exec_(textwrap.dedent(''' 71 @checking('for a thing', lambda x: x) 72 def foo(value): 73 return value 74 '''), sandbox) 75 76 foo = sandbox['foo'] 77 78 out.truncate(0) 79 foo(True) 80 self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') 81 82 out.truncate(0) 83 foo(False) 84 self.assertEqual(out.getvalue(), 'checking for a thing... no\n') 85 86 out.truncate(0) 87 foo(42) 88 self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') 89 90 out.truncate(0) 91 foo('foo') 92 self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') 93 94 out.truncate(0) 95 data = ['foo', 'bar'] 96 foo(data) 97 self.assertEqual(out.getvalue(), 'checking for a thing... %r\n' % data) 98 99 exec_(textwrap.dedent(''' 100 def munge(x): 101 if not x: 102 return 'not found' 103 if isinstance(x, (str, bool, int)): 104 return x 105 return ' '.join(x) 106 107 @checking('for a thing', munge) 108 def foo(value): 109 return value 110 '''), sandbox) 111 112 foo = sandbox['foo'] 113 114 out.truncate(0) 115 foo(True) 116 self.assertEqual(out.getvalue(), 'checking for a thing... yes\n') 117 118 out.truncate(0) 119 foo(False) 120 self.assertEqual(out.getvalue(), 'checking for a thing... not found\n') 121 122 out.truncate(0) 123 foo(42) 124 self.assertEqual(out.getvalue(), 'checking for a thing... 42\n') 125 126 out.truncate(0) 127 foo('foo') 128 self.assertEqual(out.getvalue(), 'checking for a thing... foo\n') 129 130 out.truncate(0) 131 foo(['foo', 'bar']) 132 self.assertEqual(out.getvalue(), 'checking for a thing... foo bar\n') 133 134 KNOWN_A = ensure_exe_extension(mozpath.abspath('/usr/bin/known-a')) 135 KNOWN_B = ensure_exe_extension(mozpath.abspath('/usr/local/bin/known-b')) 136 KNOWN_C = ensure_exe_extension(mozpath.abspath('/home/user/bin/known c')) 137 OTHER_A = ensure_exe_extension(mozpath.abspath('/lib/other/known-a')) 138 139 def get_result(self, command='', args=[], environ={}, 140 prog='/bin/configure', extra_paths=None, 141 includes=('util.configure', 'checks.configure')): 142 config = {} 143 out = StringIO() 144 paths = { 145 self.KNOWN_A: None, 146 self.KNOWN_B: None, 147 self.KNOWN_C: None, 148 } 149 if extra_paths: 150 paths.update(extra_paths) 151 environ = dict(environ) 152 if 'PATH' not in environ: 153 environ['PATH'] = os.pathsep.join(os.path.dirname(p) for p in paths) 154 paths[self.OTHER_A] = None 155 sandbox = ConfigureTestSandbox(paths, config, environ, [prog] + args, 156 out, out) 157 base_dir = os.path.join(topsrcdir, 'build', 'moz.configure') 158 for f in includes: 159 sandbox.include_file(os.path.join(base_dir, f)) 160 161 status = 0 162 try: 163 exec_(command, sandbox) 164 sandbox.run() 165 except SystemExit as e: 166 status = e.code 167 168 return config, out.getvalue(), status 169 170 def test_check_prog(self): 171 config, out, status = self.get_result( 172 'check_prog("FOO", ("known-a",))') 173 self.assertEqual(status, 0) 174 self.assertEqual(config, {'FOO': self.KNOWN_A}) 175 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_A) 176 177 config, out, status = self.get_result( 178 'check_prog("FOO", ("unknown", "known-b", "known c"))') 179 self.assertEqual(status, 0) 180 self.assertEqual(config, {'FOO': self.KNOWN_B}) 181 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_B) 182 183 config, out, status = self.get_result( 184 'check_prog("FOO", ("unknown", "unknown-2", "known c"))') 185 self.assertEqual(status, 0) 186 self.assertEqual(config, {'FOO': fake_short_path(self.KNOWN_C)}) 187 self.assertEqual(out, "checking for foo... '%s'\n" 188 % fake_short_path(self.KNOWN_C)) 189 190 config, out, status = self.get_result( 191 'check_prog("FOO", ("unknown",))') 192 self.assertEqual(status, 1) 193 self.assertEqual(config, {}) 194 self.assertEqual(out, textwrap.dedent('''\ 195 checking for foo... not found 196 DEBUG: foo: Trying unknown 197 ERROR: Cannot find foo 198 ''')) 199 200 config, out, status = self.get_result( 201 'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"))') 202 self.assertEqual(status, 1) 203 self.assertEqual(config, {}) 204 self.assertEqual(out, textwrap.dedent('''\ 205 checking for foo... not found 206 DEBUG: foo: Trying unknown 207 DEBUG: foo: Trying unknown-2 208 DEBUG: foo: Trying 'unknown 3' 209 ERROR: Cannot find foo 210 ''')) 211 212 config, out, status = self.get_result( 213 'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"), ' 214 'allow_missing=True)') 215 self.assertEqual(status, 0) 216 self.assertEqual(config, {'FOO': ':'}) 217 self.assertEqual(out, 'checking for foo... not found\n') 218 219 @unittest.skipIf(not sys.platform.startswith('win'), 'Windows-only test') 220 def test_check_prog_exe(self): 221 config, out, status = self.get_result( 222 'check_prog("FOO", ("unknown", "known-b", "known c"))', 223 ['FOO=known-a.exe']) 224 self.assertEqual(status, 0) 225 self.assertEqual(config, {'FOO': self.KNOWN_A}) 226 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_A) 227 228 config, out, status = self.get_result( 229 'check_prog("FOO", ("unknown", "known-b", "known c"))', 230 ['FOO=%s' % os.path.splitext(self.KNOWN_A)[0]]) 231 self.assertEqual(status, 0) 232 self.assertEqual(config, {'FOO': self.KNOWN_A}) 233 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_A) 234 235 236 def test_check_prog_with_args(self): 237 config, out, status = self.get_result( 238 'check_prog("FOO", ("unknown", "known-b", "known c"))', 239 ['FOO=known-a']) 240 self.assertEqual(status, 0) 241 self.assertEqual(config, {'FOO': self.KNOWN_A}) 242 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_A) 243 244 config, out, status = self.get_result( 245 'check_prog("FOO", ("unknown", "known-b", "known c"))', 246 ['FOO=%s' % self.KNOWN_A]) 247 self.assertEqual(status, 0) 248 self.assertEqual(config, {'FOO': self.KNOWN_A}) 249 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_A) 250 251 path = self.KNOWN_B.replace('known-b', 'known-a') 252 config, out, status = self.get_result( 253 'check_prog("FOO", ("unknown", "known-b", "known c"))', 254 ['FOO=%s' % path]) 255 self.assertEqual(status, 1) 256 self.assertEqual(config, {}) 257 self.assertEqual(out, textwrap.dedent('''\ 258 checking for foo... not found 259 DEBUG: foo: Trying %s 260 ERROR: Cannot find foo 261 ''') % path) 262 263 config, out, status = self.get_result( 264 'check_prog("FOO", ("unknown",))', 265 ['FOO=known c']) 266 self.assertEqual(status, 0) 267 self.assertEqual(config, {'FOO': fake_short_path(self.KNOWN_C)}) 268 self.assertEqual(out, "checking for foo... '%s'\n" 269 % fake_short_path(self.KNOWN_C)) 270 271 config, out, status = self.get_result( 272 'check_prog("FOO", ("unknown", "unknown-2", "unknown 3"), ' 273 'allow_missing=True)', ['FOO=unknown']) 274 self.assertEqual(status, 1) 275 self.assertEqual(config, {}) 276 self.assertEqual(out, textwrap.dedent('''\ 277 checking for foo... not found 278 DEBUG: foo: Trying unknown 279 ERROR: Cannot find foo 280 ''')) 281 282 def test_check_prog_what(self): 283 config, out, status = self.get_result( 284 'check_prog("CC", ("known-a",), what="the target C compiler")') 285 self.assertEqual(status, 0) 286 self.assertEqual(config, {'CC': self.KNOWN_A}) 287 self.assertEqual( 288 out, 'checking for the target C compiler... %s\n' % self.KNOWN_A) 289 290 config, out, status = self.get_result( 291 'check_prog("CC", ("unknown", "unknown-2", "unknown 3"),' 292 ' what="the target C compiler")') 293 self.assertEqual(status, 1) 294 self.assertEqual(config, {}) 295 self.assertEqual(out, textwrap.dedent('''\ 296 checking for the target C compiler... not found 297 DEBUG: cc: Trying unknown 298 DEBUG: cc: Trying unknown-2 299 DEBUG: cc: Trying 'unknown 3' 300 ERROR: Cannot find the target C compiler 301 ''')) 302 303 def test_check_prog_input(self): 304 config, out, status = self.get_result(textwrap.dedent(''' 305 option("--with-ccache", nargs=1, help="ccache") 306 check_prog("CCACHE", ("known-a",), input="--with-ccache") 307 '''), ['--with-ccache=known-b']) 308 self.assertEqual(status, 0) 309 self.assertEqual(config, {'CCACHE': self.KNOWN_B}) 310 self.assertEqual(out, 'checking for ccache... %s\n' % self.KNOWN_B) 311 312 script = textwrap.dedent(''' 313 option(env="CC", nargs=1, help="compiler") 314 @depends("CC") 315 def compiler(value): 316 return value[0].split()[0] if value else None 317 check_prog("CC", ("known-a",), input=compiler) 318 ''') 319 config, out, status = self.get_result(script) 320 self.assertEqual(status, 0) 321 self.assertEqual(config, {'CC': self.KNOWN_A}) 322 self.assertEqual(out, 'checking for cc... %s\n' % self.KNOWN_A) 323 324 config, out, status = self.get_result(script, ['CC=known-b']) 325 self.assertEqual(status, 0) 326 self.assertEqual(config, {'CC': self.KNOWN_B}) 327 self.assertEqual(out, 'checking for cc... %s\n' % self.KNOWN_B) 328 329 config, out, status = self.get_result(script, ['CC=known-b -m32']) 330 self.assertEqual(status, 0) 331 self.assertEqual(config, {'CC': self.KNOWN_B}) 332 self.assertEqual(out, 'checking for cc... %s\n' % self.KNOWN_B) 333 334 def test_check_prog_progs(self): 335 config, out, status = self.get_result( 336 'check_prog("FOO", ())') 337 self.assertEqual(status, 0) 338 self.assertEqual(config, {}) 339 self.assertEqual(out, '') 340 341 config, out, status = self.get_result( 342 'check_prog("FOO", ())', ['FOO=known-a']) 343 self.assertEqual(status, 0) 344 self.assertEqual(config, {'FOO': self.KNOWN_A}) 345 self.assertEqual(out, 'checking for foo... %s\n' % self.KNOWN_A) 346 347 script = textwrap.dedent(''' 348 option(env="TARGET", nargs=1, default="linux", help="target") 349 @depends("TARGET") 350 def compiler(value): 351 if value: 352 if value[0] == "linux": 353 return ("gcc", "clang") 354 if value[0] == "winnt": 355 return ("cl", "clang-cl") 356 check_prog("CC", compiler) 357 ''') 358 config, out, status = self.get_result(script) 359 self.assertEqual(status, 1) 360 self.assertEqual(config, {}) 361 self.assertEqual(out, textwrap.dedent('''\ 362 checking for cc... not found 363 DEBUG: cc: Trying gcc 364 DEBUG: cc: Trying clang 365 ERROR: Cannot find cc 366 ''')) 367 368 config, out, status = self.get_result(script, ['TARGET=linux']) 369 self.assertEqual(status, 1) 370 self.assertEqual(config, {}) 371 self.assertEqual(out, textwrap.dedent('''\ 372 checking for cc... not found 373 DEBUG: cc: Trying gcc 374 DEBUG: cc: Trying clang 375 ERROR: Cannot find cc 376 ''')) 377 378 config, out, status = self.get_result(script, ['TARGET=winnt']) 379 self.assertEqual(status, 1) 380 self.assertEqual(config, {}) 381 self.assertEqual(out, textwrap.dedent('''\ 382 checking for cc... not found 383 DEBUG: cc: Trying cl 384 DEBUG: cc: Trying clang-cl 385 ERROR: Cannot find cc 386 ''')) 387 388 config, out, status = self.get_result(script, ['TARGET=none']) 389 self.assertEqual(status, 0) 390 self.assertEqual(config, {}) 391 self.assertEqual(out, '') 392 393 config, out, status = self.get_result(script, ['TARGET=winnt', 394 'CC=known-a']) 395 self.assertEqual(status, 0) 396 self.assertEqual(config, {'CC': self.KNOWN_A}) 397 self.assertEqual(out, 'checking for cc... %s\n' % self.KNOWN_A) 398 399 config, out, status = self.get_result(script, ['TARGET=none', 400 'CC=known-a']) 401 self.assertEqual(status, 0) 402 self.assertEqual(config, {'CC': self.KNOWN_A}) 403 self.assertEqual(out, 'checking for cc... %s\n' % self.KNOWN_A) 404 405 def test_check_prog_configure_error(self): 406 with self.assertRaises(ConfigureError) as e: 407 self.get_result('check_prog("FOO", "foo")') 408 409 self.assertEqual(e.exception.message, 410 'progs must resolve to a list or tuple!') 411 412 with self.assertRaises(ConfigureError) as e: 413 self.get_result( 414 'foo = depends(when=True)(lambda: ("a", "b"))\n' 415 'check_prog("FOO", ("known-a",), input=foo)' 416 ) 417 418 self.assertEqual(e.exception.message, 419 'input must resolve to a tuple or a list with a ' 420 'single element, or a string') 421 422 with self.assertRaises(ConfigureError) as e: 423 self.get_result( 424 'foo = depends(when=True)(lambda: {"a": "b"})\n' 425 'check_prog("FOO", ("known-a",), input=foo)' 426 ) 427 428 self.assertEqual(e.exception.message, 429 'input must resolve to a tuple or a list with a ' 430 'single element, or a string') 431 432 def test_check_prog_with_path(self): 433 config, out, status = self.get_result('check_prog("A", ("known-a",), paths=["/some/path"])') 434 self.assertEqual(status, 1) 435 self.assertEqual(config, {}) 436 self.assertEqual(out, textwrap.dedent('''\ 437 checking for a... not found 438 DEBUG: a: Trying known-a 439 ERROR: Cannot find a 440 ''')) 441 442 config, out, status = self.get_result('check_prog("A", ("known-a",), paths=["%s"])' % 443 os.path.dirname(self.OTHER_A)) 444 self.assertEqual(status, 0) 445 self.assertEqual(config, {'A': self.OTHER_A}) 446 self.assertEqual(out, textwrap.dedent('''\ 447 checking for a... %s 448 ''' % self.OTHER_A)) 449 450 dirs = map(mozpath.dirname, (self.OTHER_A, self.KNOWN_A)) 451 config, out, status = self.get_result(textwrap.dedent('''\ 452 check_prog("A", ("known-a",), paths=["%s"]) 453 ''' % os.pathsep.join(dirs))) 454 self.assertEqual(status, 0) 455 self.assertEqual(config, {'A': self.OTHER_A}) 456 self.assertEqual(out, textwrap.dedent('''\ 457 checking for a... %s 458 ''' % self.OTHER_A)) 459 460 dirs = map(mozpath.dirname, (self.KNOWN_A, self.KNOWN_B)) 461 config, out, status = self.get_result(textwrap.dedent('''\ 462 check_prog("A", ("known-a",), paths=["%s", "%s"]) 463 ''' % (os.pathsep.join(dirs), self.OTHER_A))) 464 self.assertEqual(status, 0) 465 self.assertEqual(config, {'A': self.KNOWN_A}) 466 self.assertEqual(out, textwrap.dedent('''\ 467 checking for a... %s 468 ''' % self.KNOWN_A)) 469 470 config, out, status = self.get_result('check_prog("A", ("known-a",), paths="%s")' % 471 os.path.dirname(self.OTHER_A)) 472 473 self.assertEqual(status, 1) 474 self.assertEqual(config, {}) 475 self.assertEqual(out, textwrap.dedent('''\ 476 checking for a... 477 DEBUG: a: Trying known-a 478 ERROR: Paths provided to find_program must be a list of strings, not %r 479 ''' % mozpath.dirname(self.OTHER_A))) 480 481 def test_java_tool_checks(self): 482 includes = ('util.configure', 'checks.configure', 'java.configure') 483 484 def mock_valid_javac(_, args): 485 if len(args) == 1 and args[0] == '-version': 486 return 0, '1.8', '' 487 self.fail("Unexpected arguments to mock_valid_javac: %s" % args) 488 489 # A valid set of tools in a standard location. 490 java = mozpath.abspath('/usr/bin/java') 491 javah = mozpath.abspath('/usr/bin/javah') 492 javac = mozpath.abspath('/usr/bin/javac') 493 jar = mozpath.abspath('/usr/bin/jar') 494 jarsigner = mozpath.abspath('/usr/bin/jarsigner') 495 keytool = mozpath.abspath('/usr/bin/keytool') 496 497 paths = { 498 java: None, 499 javah: None, 500 javac: mock_valid_javac, 501 jar: None, 502 jarsigner: None, 503 keytool: None, 504 } 505 506 config, out, status = self.get_result(includes=includes, extra_paths=paths) 507 self.assertEqual(status, 0) 508 self.assertEqual(config, { 509 'JAVA': java, 510 'JAVAH': javah, 511 'JAVAC': javac, 512 'JAR': jar, 513 'JARSIGNER': jarsigner, 514 'KEYTOOL': keytool, 515 }) 516 self.assertEqual(out, textwrap.dedent('''\ 517 checking for java... %s 518 checking for javah... %s 519 checking for jar... %s 520 checking for jarsigner... %s 521 checking for keytool... %s 522 checking for javac... %s 523 checking for javac version... 1.8 524 ''' % (java, javah, jar, jarsigner, keytool, javac))) 525 526 # An alternative valid set of tools referred to by JAVA_HOME. 527 alt_java = mozpath.abspath('/usr/local/bin/java') 528 alt_javah = mozpath.abspath('/usr/local/bin/javah') 529 alt_javac = mozpath.abspath('/usr/local/bin/javac') 530 alt_jar = mozpath.abspath('/usr/local/bin/jar') 531 alt_jarsigner = mozpath.abspath('/usr/local/bin/jarsigner') 532 alt_keytool = mozpath.abspath('/usr/local/bin/keytool') 533 alt_java_home = mozpath.dirname(mozpath.dirname(alt_java)) 534 535 paths.update({ 536 alt_java: None, 537 alt_javah: None, 538 alt_javac: mock_valid_javac, 539 alt_jar: None, 540 alt_jarsigner: None, 541 alt_keytool: None, 542 }) 543 544 config, out, status = self.get_result(includes=includes, 545 extra_paths=paths, 546 environ={ 547 'JAVA_HOME': alt_java_home, 548 'PATH': mozpath.dirname(java) 549 }) 550 self.assertEqual(status, 0) 551 self.assertEqual(config, { 552 'JAVA': alt_java, 553 'JAVAH': alt_javah, 554 'JAVAC': alt_javac, 555 'JAR': alt_jar, 556 'JARSIGNER': alt_jarsigner, 557 'KEYTOOL': alt_keytool, 558 }) 559 self.assertEqual(out, textwrap.dedent('''\ 560 checking for java... %s 561 checking for javah... %s 562 checking for jar... %s 563 checking for jarsigner... %s 564 checking for keytool... %s 565 checking for javac... %s 566 checking for javac version... 1.8 567 ''' % (alt_java, alt_javah, alt_jar, alt_jarsigner, 568 alt_keytool, alt_javac))) 569 570 # We can use --with-java-bin-path instead of JAVA_HOME to similar 571 # effect. 572 config, out, status = self.get_result( 573 args=['--with-java-bin-path=%s' % mozpath.dirname(alt_java)], 574 includes=includes, 575 extra_paths=paths, 576 environ={ 577 'PATH': mozpath.dirname(java) 578 }) 579 self.assertEqual(status, 0) 580 self.assertEqual(config, { 581 'JAVA': alt_java, 582 'JAVAH': alt_javah, 583 'JAVAC': alt_javac, 584 'JAR': alt_jar, 585 'JARSIGNER': alt_jarsigner, 586 'KEYTOOL': alt_keytool, 587 }) 588 self.assertEqual(out, textwrap.dedent('''\ 589 checking for java... %s 590 checking for javah... %s 591 checking for jar... %s 592 checking for jarsigner... %s 593 checking for keytool... %s 594 checking for javac... %s 595 checking for javac version... 1.8 596 ''' % (alt_java, alt_javah, alt_jar, alt_jarsigner, 597 alt_keytool, alt_javac))) 598 599 # If --with-java-bin-path and JAVA_HOME are both set, 600 # --with-java-bin-path takes precedence. 601 config, out, status = self.get_result( 602 args=['--with-java-bin-path=%s' % mozpath.dirname(alt_java)], 603 includes=includes, 604 extra_paths=paths, 605 environ={ 606 'PATH': mozpath.dirname(java), 607 'JAVA_HOME': mozpath.dirname(mozpath.dirname(java)), 608 }) 609 self.assertEqual(status, 0) 610 self.assertEqual(config, { 611 'JAVA': alt_java, 612 'JAVAH': alt_javah, 613 'JAVAC': alt_javac, 614 'JAR': alt_jar, 615 'JARSIGNER': alt_jarsigner, 616 'KEYTOOL': alt_keytool, 617 }) 618 self.assertEqual(out, textwrap.dedent('''\ 619 checking for java... %s 620 checking for javah... %s 621 checking for jar... %s 622 checking for jarsigner... %s 623 checking for keytool... %s 624 checking for javac... %s 625 checking for javac version... 1.8 626 ''' % (alt_java, alt_javah, alt_jar, alt_jarsigner, 627 alt_keytool, alt_javac))) 628 629 def mock_old_javac(_, args): 630 if len(args) == 1 and args[0] == '-version': 631 return 0, '1.6.9', '' 632 self.fail("Unexpected arguments to mock_old_javac: %s" % args) 633 634 # An old javac is fatal. 635 paths[javac] = mock_old_javac 636 config, out, status = self.get_result(includes=includes, 637 extra_paths=paths, 638 environ={ 639 'PATH': mozpath.dirname(java) 640 }) 641 self.assertEqual(status, 1) 642 self.assertEqual(config, { 643 'JAVA': java, 644 'JAVAH': javah, 645 'JAVAC': javac, 646 'JAR': jar, 647 'JARSIGNER': jarsigner, 648 'KEYTOOL': keytool, 649 }) 650 self.assertEqual(out, textwrap.dedent('''\ 651 checking for java... %s 652 checking for javah... %s 653 checking for jar... %s 654 checking for jarsigner... %s 655 checking for keytool... %s 656 checking for javac... %s 657 checking for javac version... 658 ERROR: javac 1.8 or higher is required (found 1.6.9). Check the JAVA_HOME environment variable. 659 ''' % (java, javah, jar, jarsigner, keytool, javac))) 660 661 # Any missing tool is fatal when these checks run. 662 del paths[jarsigner] 663 config, out, status = self.get_result(includes=includes, 664 extra_paths=paths, 665 environ={ 666 'PATH': mozpath.dirname(java) 667 }) 668 self.assertEqual(status, 1) 669 self.assertEqual(config, { 670 'JAVA': java, 671 'JAVAH': javah, 672 'JAR': jar, 673 'JARSIGNER': ':', 674 }) 675 self.assertEqual(out, textwrap.dedent('''\ 676 checking for java... %s 677 checking for javah... %s 678 checking for jar... %s 679 checking for jarsigner... not found 680 ERROR: The program jarsigner was not found. Set $JAVA_HOME to your Java SDK directory or use '--with-java-bin-path={java-bin-dir}' 681 ''' % (java, javah, jar))) 682 683 def test_pkg_check_modules(self): 684 mock_pkg_config_version = '0.10.0' 685 mock_pkg_config_path = mozpath.abspath('/usr/bin/pkg-config') 686 687 def mock_pkg_config(_, args): 688 if args[0:2] == ['--errors-to-stdout', '--print-errors']: 689 assert len(args) == 3 690 package = args[2] 691 if package == 'unknown': 692 return (1, "Package unknown was not found in the pkg-config search path.\n" 693 "Perhaps you should add the directory containing `unknown.pc'\n" 694 "to the PKG_CONFIG_PATH environment variable\n" 695 "No package 'unknown' found", '') 696 if package == 'valid': 697 return 0, '', '' 698 if package == 'new > 1.1': 699 return 1, "Requested 'new > 1.1' but version of new is 1.1", '' 700 if args[0] == '--cflags': 701 assert len(args) == 2 702 return 0, '-I/usr/include/%s' % args[1], '' 703 if args[0] == '--libs': 704 assert len(args) == 2 705 return 0, '-l%s' % args[1], '' 706 if args[0] == '--version': 707 return 0, mock_pkg_config_version, '' 708 self.fail("Unexpected arguments to mock_pkg_config: %s" % args) 709 710 def get_result(cmd, args=[], extra_paths=None): 711 return self.get_result(textwrap.dedent('''\ 712 option('--disable-compile-environment', help='compile env') 713 include('%(topsrcdir)s/build/moz.configure/util.configure') 714 include('%(topsrcdir)s/build/moz.configure/checks.configure') 715 include('%(topsrcdir)s/build/moz.configure/pkg.configure') 716 ''' % {'topsrcdir': topsrcdir}) + cmd, args=args, extra_paths=extra_paths, 717 includes=()) 718 719 extra_paths = { 720 mock_pkg_config_path: mock_pkg_config, 721 } 722 includes = ('util.configure', 'checks.configure', 'pkg.configure') 723 724 config, output, status = get_result("pkg_check_modules('MOZ_VALID', 'valid')") 725 self.assertEqual(status, 1) 726 self.assertEqual(output, textwrap.dedent('''\ 727 checking for pkg_config... not found 728 ERROR: *** The pkg-config script could not be found. Make sure it is 729 *** in your path, or set the PKG_CONFIG environment variable 730 *** to the full path to pkg-config. 731 ''')) 732 733 734 config, output, status = get_result("pkg_check_modules('MOZ_VALID', 'valid')", 735 extra_paths=extra_paths) 736 self.assertEqual(status, 0) 737 self.assertEqual(output, textwrap.dedent('''\ 738 checking for pkg_config... %s 739 checking for pkg-config version... %s 740 checking for valid... yes 741 checking MOZ_VALID_CFLAGS... -I/usr/include/valid 742 checking MOZ_VALID_LIBS... -lvalid 743 ''' % (mock_pkg_config_path, mock_pkg_config_version))) 744 self.assertEqual(config, { 745 'PKG_CONFIG': mock_pkg_config_path, 746 'MOZ_VALID_CFLAGS': ('-I/usr/include/valid',), 747 'MOZ_VALID_LIBS': ('-lvalid',), 748 }) 749 750 config, output, status = get_result("pkg_check_modules('MOZ_UKNOWN', 'unknown')", 751 extra_paths=extra_paths) 752 self.assertEqual(status, 1) 753 self.assertEqual(output, textwrap.dedent('''\ 754 checking for pkg_config... %s 755 checking for pkg-config version... %s 756 checking for unknown... no 757 ERROR: Package unknown was not found in the pkg-config search path. 758 ERROR: Perhaps you should add the directory containing `unknown.pc' 759 ERROR: to the PKG_CONFIG_PATH environment variable 760 ERROR: No package 'unknown' found 761 ''' % (mock_pkg_config_path, mock_pkg_config_version))) 762 self.assertEqual(config, { 763 'PKG_CONFIG': mock_pkg_config_path, 764 }) 765 766 config, output, status = get_result("pkg_check_modules('MOZ_NEW', 'new > 1.1')", 767 extra_paths=extra_paths) 768 self.assertEqual(status, 1) 769 self.assertEqual(output, textwrap.dedent('''\ 770 checking for pkg_config... %s 771 checking for pkg-config version... %s 772 checking for new > 1.1... no 773 ERROR: Requested 'new > 1.1' but version of new is 1.1 774 ''' % (mock_pkg_config_path, mock_pkg_config_version))) 775 self.assertEqual(config, { 776 'PKG_CONFIG': mock_pkg_config_path, 777 }) 778 779 # allow_missing makes missing packages non-fatal. 780 cmd = textwrap.dedent('''\ 781 have_new_module = pkg_check_modules('MOZ_NEW', 'new > 1.1', allow_missing=True) 782 @depends(have_new_module) 783 def log_new_module_error(mod): 784 if mod is not True: 785 log.info('Module not found.') 786 ''') 787 788 config, output, status = get_result(cmd, extra_paths=extra_paths) 789 self.assertEqual(status, 0) 790 self.assertEqual(output, textwrap.dedent('''\ 791 checking for pkg_config... %s 792 checking for pkg-config version... %s 793 checking for new > 1.1... no 794 WARNING: Requested 'new > 1.1' but version of new is 1.1 795 Module not found. 796 ''' % (mock_pkg_config_path, mock_pkg_config_version))) 797 self.assertEqual(config, { 798 'PKG_CONFIG': mock_pkg_config_path, 799 }) 800 801 config, output, status = get_result(cmd, 802 args=['--disable-compile-environment'], 803 extra_paths=extra_paths) 804 self.assertEqual(status, 0) 805 self.assertEqual(output, 'Module not found.\n') 806 self.assertEqual(config, {}) 807 808 def mock_old_pkg_config(_, args): 809 if args[0] == '--version': 810 return 0, '0.8.10', '' 811 self.fail("Unexpected arguments to mock_old_pkg_config: %s" % args) 812 813 extra_paths = { 814 mock_pkg_config_path: mock_old_pkg_config, 815 } 816 817 config, output, status = get_result("pkg_check_modules('MOZ_VALID', 'valid')", 818 extra_paths=extra_paths) 819 self.assertEqual(status, 1) 820 self.assertEqual(output, textwrap.dedent('''\ 821 checking for pkg_config... %s 822 checking for pkg-config version... 0.8.10 823 ERROR: *** Your version of pkg-config is too old. You need version 0.9.0 or newer. 824 ''' % mock_pkg_config_path)) 825 826 def test_simple_keyfile(self): 827 includes = ('util.configure', 'checks.configure', 'keyfiles.configure') 828 829 config, output, status = self.get_result( 830 "simple_keyfile('Mozilla API')", includes=includes) 831 self.assertEqual(status, 0) 832 self.assertEqual(output, textwrap.dedent('''\ 833 checking for the Mozilla API key... no 834 ''')) 835 self.assertEqual(config, { 836 'MOZ_MOZILLA_API_KEY': 'no-mozilla-api-key', 837 }) 838 839 config, output, status = self.get_result( 840 "simple_keyfile('Mozilla API')", 841 args=['--with-mozilla-api-keyfile=/foo/bar/does/not/exist'], 842 includes=includes) 843 self.assertEqual(status, 1) 844 self.assertEqual(output, textwrap.dedent('''\ 845 checking for the Mozilla API key... no 846 ERROR: '/foo/bar/does/not/exist': No such file or directory. 847 ''')) 848 self.assertEqual(config, {}) 849 850 with MockedOpen({'key': ''}): 851 config, output, status = self.get_result( 852 "simple_keyfile('Mozilla API')", 853 args=['--with-mozilla-api-keyfile=key'], 854 includes=includes) 855 self.assertEqual(status, 1) 856 self.assertEqual(output, textwrap.dedent('''\ 857 checking for the Mozilla API key... no 858 ERROR: 'key' is empty. 859 ''')) 860 self.assertEqual(config, {}) 861 862 with MockedOpen({'key': 'fake-key\n'}): 863 config, output, status = self.get_result( 864 "simple_keyfile('Mozilla API')", 865 args=['--with-mozilla-api-keyfile=key'], 866 includes=includes) 867 self.assertEqual(status, 0) 868 self.assertEqual(output, textwrap.dedent('''\ 869 checking for the Mozilla API key... yes 870 ''')) 871 self.assertEqual(config, { 872 'MOZ_MOZILLA_API_KEY': 'fake-key', 873 }) 874 875 with MockedOpen({'default': 'default-key\n'}): 876 config, output, status = self.get_result( 877 "simple_keyfile('Mozilla API', default='default')", 878 includes=includes) 879 self.assertEqual(status, 0) 880 self.assertEqual(output, textwrap.dedent('''\ 881 checking for the Mozilla API key... yes 882 ''')) 883 self.assertEqual(config, { 884 'MOZ_MOZILLA_API_KEY': 'default-key', 885 }) 886 887 with MockedOpen({'default': 'default-key\n', 888 'key': 'fake-key\n'}): 889 config, output, status = self.get_result( 890 "simple_keyfile('Mozilla API', default='key')", 891 includes=includes) 892 self.assertEqual(status, 0) 893 self.assertEqual(output, textwrap.dedent('''\ 894 checking for the Mozilla API key... yes 895 ''')) 896 self.assertEqual(config, { 897 'MOZ_MOZILLA_API_KEY': 'fake-key', 898 }) 899 900 def test_id_and_secret_keyfile(self): 901 includes = ('util.configure', 'checks.configure', 'keyfiles.configure') 902 903 config, output, status = self.get_result( 904 "id_and_secret_keyfile('Bing API')", includes=includes) 905 self.assertEqual(status, 0) 906 self.assertEqual(output, textwrap.dedent('''\ 907 checking for the Bing API key... no 908 ''')) 909 self.assertEqual(config, { 910 'MOZ_BING_API_CLIENTID': 'no-bing-api-clientid', 911 'MOZ_BING_API_KEY': 'no-bing-api-key', 912 }) 913 914 config, output, status = self.get_result( 915 "id_and_secret_keyfile('Bing API')", 916 args=['--with-bing-api-keyfile=/foo/bar/does/not/exist'], 917 includes=includes) 918 self.assertEqual(status, 1) 919 self.assertEqual(output, textwrap.dedent('''\ 920 checking for the Bing API key... no 921 ERROR: '/foo/bar/does/not/exist': No such file or directory. 922 ''')) 923 self.assertEqual(config, {}) 924 925 with MockedOpen({'key': ''}): 926 config, output, status = self.get_result( 927 "id_and_secret_keyfile('Bing API')", 928 args=['--with-bing-api-keyfile=key'], 929 includes=includes) 930 self.assertEqual(status, 1) 931 self.assertEqual(output, textwrap.dedent('''\ 932 checking for the Bing API key... no 933 ERROR: 'key' is empty. 934 ''')) 935 self.assertEqual(config, {}) 936 937 with MockedOpen({'key': 'fake-id fake-key\n'}): 938 config, output, status = self.get_result( 939 "id_and_secret_keyfile('Bing API')", 940 args=['--with-bing-api-keyfile=key'], 941 includes=includes) 942 self.assertEqual(status, 0) 943 self.assertEqual(output, textwrap.dedent('''\ 944 checking for the Bing API key... yes 945 ''')) 946 self.assertEqual(config, { 947 'MOZ_BING_API_CLIENTID': 'fake-id', 948 'MOZ_BING_API_KEY': 'fake-key', 949 }) 950 951 with MockedOpen({'key': 'fake-key\n'}): 952 config, output, status = self.get_result( 953 "id_and_secret_keyfile('Bing API')", 954 args=['--with-bing-api-keyfile=key'], 955 includes=includes) 956 self.assertEqual(status, 1) 957 self.assertEqual(output, textwrap.dedent('''\ 958 checking for the Bing API key... no 959 ERROR: Bing API key file has an invalid format. 960 ''')) 961 self.assertEqual(config, {}) 962 963 with MockedOpen({'default-key': 'default-id default-key\n'}): 964 config, output, status = self.get_result( 965 "id_and_secret_keyfile('Bing API', default='default-key')", 966 includes=includes) 967 self.assertEqual(status, 0) 968 self.assertEqual(output, textwrap.dedent('''\ 969 checking for the Bing API key... yes 970 ''')) 971 self.assertEqual(config, { 972 'MOZ_BING_API_CLIENTID': 'default-id', 973 'MOZ_BING_API_KEY': 'default-key', 974 }) 975 976 with MockedOpen({'default-key': 'default-id default-key\n', 977 'key': 'fake-id fake-key\n'}): 978 config, output, status = self.get_result( 979 "id_and_secret_keyfile('Bing API', default='default-key')", 980 args=['--with-bing-api-keyfile=key'], 981 includes=includes) 982 self.assertEqual(status, 0) 983 self.assertEqual(output, textwrap.dedent('''\ 984 checking for the Bing API key... yes 985 ''')) 986 self.assertEqual(config, { 987 'MOZ_BING_API_CLIENTID': 'fake-id', 988 'MOZ_BING_API_KEY': 'fake-key', 989 }) 990 991 992if __name__ == '__main__': 993 main() 994