blob: 0f39c0c448e29ed4dd111ee242627742d8a7afe3 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
LIB_DIR = os.path.dirname(SCRIPT_DIR)
TOOLS_DIR = os.path.dirname(LIB_DIR)
SDK_DIR = os.path.dirname(TOOLS_DIR)
DATA_DIR = os.path.join(SCRIPT_DIR, 'data')
BUILD_TOOLS_DIR = os.path.join(SDK_DIR, 'build_tools')
sys.path.append(LIB_DIR)
sys.path.append(TOOLS_DIR)
sys.path.append(BUILD_TOOLS_DIR)
import build_paths
import get_shared_deps
import getos
TOOLCHAIN_OUT = os.path.join(build_paths.OUT_DIR, 'sdk_tests', 'toolchain')
NACL_X86_GLIBC_TOOLCHAIN = os.path.join(TOOLCHAIN_OUT,
'%s_x86' % getos.GetPlatform(),
'nacl_x86_glibc')
def StripDependencies(deps):
'''Strip the dirnames and version suffixes from
a list of nexe dependencies.
e.g:
/path/to/libpthread.so.1a2d3fsa -> libpthread.so
'''
names = []
for name in deps:
name = os.path.basename(name)
if '.so.' in name:
name = name.rsplit('.', 1)[0]
names.append(name)
return names
class TestGetNeeded(unittest.TestCase):
def setUp(self):
self.tempdir = None
self.toolchain = NACL_X86_GLIBC_TOOLCHAIN
self.objdump = os.path.join(self.toolchain, 'bin', 'i686-nacl-objdump')
if os.name == 'nt':
self.objdump += '.exe'
self.Mktemp()
self.dyn_nexe = self.createTestNexe('test_dynamic_x86_32.nexe', 'i686')
self.dyn_deps = set(['libc.so', 'runnable-ld.so',
'libgcc_s.so', 'libpthread.so'])
def tearDown(self):
if self.tempdir:
shutil.rmtree(self.tempdir)
def Mktemp(self):
self.tempdir = tempfile.mkdtemp()
def createTestNexe(self, name, arch):
'''Create an empty test .nexe file for use in create_nmf tests.
This is used rather than checking in test binaries since the
checked in binaries depend on .so files that only exist in the
certain SDK that built them.
'''
compiler = os.path.join(self.toolchain, 'bin', '%s-nacl-g++' % arch)
if os.name == 'nt':
compiler += '.exe'
os.environ['CYGWIN'] = 'nodosfilewarning'
program = 'int main() { return 0; }'
name = os.path.join(self.tempdir, name)
cmd = [compiler, '-pthread', '-x' , 'c', '-o', name, '-']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
p.communicate(input=program)
self.assertEqual(p.returncode, 0)
return name
def testStatic(self):
nexe = os.path.join(DATA_DIR, 'test_static_x86_32.nexe')
# GetNeeded should not raise an error if objdump is not set, but the .nexe
# is statically linked.
objdump = None
lib_path = []
needed = get_shared_deps.GetNeeded([nexe], objdump, lib_path)
# static nexe should have exactly one needed file
self.assertEqual(len(needed), 1)
self.assertEqual(needed.keys()[0], nexe)
# arch of needed file should be x86-32
arch = needed.values()[0]
self.assertEqual(arch, 'x86-32')
def testDynamic(self):
libdir = os.path.join(self.toolchain, 'x86_64-nacl', 'lib32')
needed = get_shared_deps.GetNeeded([self.dyn_nexe],
lib_path=[libdir],
objdump=self.objdump)
names = needed.keys()
# this nexe has 5 dependencies
expected = set(self.dyn_deps)
expected.add(os.path.basename(self.dyn_nexe))
basenames = set(StripDependencies(names))
self.assertEqual(expected, basenames)
def testMissingArchLibrary(self):
libdir = os.path.join(self.toolchain, 'x86_64-nacl', 'lib32')
lib_path = [libdir]
nexes = ['libgcc_s.so.1']
# CreateNmfUtils uses the 32-bit library path, but not the 64-bit one
# so searching for a 32-bit library should succeed while searching for
# a 64-bit one should fail.
get_shared_deps.GleanFromObjdump(nexes, 'x86-32', self.objdump, lib_path)
self.assertRaises(get_shared_deps.Error,
get_shared_deps.GleanFromObjdump,
nexes, 'x86-64', self.objdump, lib_path)
def testCorrectArch(self):
lib_path = [os.path.join(self.toolchain, 'x86_64-nacl', 'lib32'),
os.path.join(self.toolchain, 'x86_64-nacl', 'lib')]
needed = get_shared_deps.GetNeeded([self.dyn_nexe],
lib_path=lib_path,
objdump=self.objdump)
for arch in needed.itervalues():
self.assertEqual(arch, 'x86-32')
if __name__ == '__main__':
unittest.main()