#!/usr/bin/python
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
import testutils
if __name__ == "__main__":
testutils.setup_environment("../../../proto")
import pkg5unittest
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
import pkg.catalog as catalog
import pkg.flavor.base as base
import pkg.flavor.depthlimitedmf as dlmf
import pkg.flavor.elf as elf
import pkg.flavor.hardlink as hl
import pkg.flavor.python as py
import pkg.flavor.script as scr
import pkg.flavor.smf_manifest as smf
import pkg.fmri as fmri
import pkg.portable as portable
import pkg.publish.dependencies as dependencies
import pkg.updatelog as updatelog
class TestDependencyAnalyzer(pkg5unittest.Pkg5TestCase):
paths = {
"authlog_path": "var/log/authlog",
"curses_path": "usr/xpg4/lib/libcurses.so.1",
"indexer_path":
"usr/lib/python2.6/vendor-packages/pkg_test/client/indexer.py",
"ksh_path": "usr/bin/ksh",
"libc_path": "lib/libc.so.1",
"pkg_path":
"usr/lib/python2.6/vendor-packages/pkg_test/client/__init__.py",
"script_path": "lib/svc/method/svc-pkg-depot",
"syslog_path": "var/log/syslog",
"py_mod_path": "usr/lib/python2.6/vendor-packages/cProfile.py",
"py_mod_path24": "usr/lib/python2.4/vendor-packages/cProfile.py"
}
smf_paths = {
"broken":
"var/svc/manifest/broken-service.xml",
"delivered_many_nodeps":
"var/svc/manifest/delivered-many-nodeps.xml",
"foreign_many_nodeps":
"var/svc/manifest/foreign-many-nodeps.xml",
"foreign_single_nodeps":
"var/svc/manifest/foreign-single-nodeps.xml",
"service_many": "var/svc/manifest/service-many.xml",
"service_single": "var/svc/manifest/service-single.xml",
"service_unknown": "var/svc/manifest/service-single-unknown.xml"
}
paths.update(smf_paths)
ext_hardlink_manf = """ \
hardlink path=usr/foo target=../%(syslog_path)s
hardlink path=usr/bar target=../%(syslog_path)s
hardlink path=baz target=%(authlog_path)s
""" % paths
int_hardlink_manf = """ \
hardlink path=usr/foo target=../%(syslog_path)s
file NOHASH group=sys mode=0644 owner=root path=%(syslog_path)s
""" % paths
int_hardlink_manf_test_symlink = """ \
hardlink path=usr/foo target=../%(syslog_path)s
file NOHASH group=sys mode=0644 owner=root path=bar/syslog
""" % paths
ext_script_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(script_path)s
""" % paths
int_script_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(script_path)s
file NOHASH group=bin mode=0755 owner=root path=%(ksh_path)s
""" % paths
ext_elf_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(curses_path)s
""" % paths
int_elf_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(libc_path)s
file NOHASH group=bin mode=0755 owner=root path=%(curses_path)s
""" % paths
ext_python_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(indexer_path)s
""" % paths
ext_python_pkg_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(pkg_path)s
""" % paths
python_mod_manf = """ \
file NOHASH group=bin mode=0755 owner=root path=%(py_mod_path)s
file NOHASH group=bin mode=0755 owner=root path=%(py_mod_path24)s
""" % paths
variant_manf_1 = """ \
set name=variant.arch value=foo value=bar value=baz
file NOHASH group=bin mode=0755 owner=root path=%(script_path)s
file NOHASH group=bin mode=0755 owner=root path=%(ksh_path)s variant.arch=foo
""" % paths
variant_manf_2 = """ \
set name=variant.arch value=foo value=bar value=baz
file NOHASH group=bin mode=0755 owner=root path=%(script_path)s variant.arch=foo
file NOHASH group=bin mode=0755 owner=root path=%(ksh_path)s variant.arch=foo
""" % paths
variant_manf_3 = """ \
set name=variant.arch value=foo value=bar value=baz
file NOHASH group=bin mode=0755 owner=root path=%(script_path)s variant.arch=bar
file NOHASH group=bin mode=0755 owner=root path=%(ksh_path)s variant.arch=foo
""" % paths
variant_manf_4 = """ \
set name=variant.arch value=foo
set name=variant.opensolaris.zone value=global value=nonglobal
file NOHASH group=bin mode=0755 owner=root path=%(script_path)s variant.opensolaris.zone=global
file NOHASH group=bin mode=0755 owner=root path=%(ksh_path)s variant.opensolaris.zone=global
""" % paths
python_abs_text = """\
#!/usr/bin/python
from __future__ import absolute_import
import os
import sys
import pkg_test.indexer_test.foobar as indexer
import pkg.search_storage as ss
from ..misc_test import EmptyI
"""
python_text = """\
#!/usr/bin/python
import os
import sys
import pkg_test.indexer_test.foobar as indexer
import pkg.search_storage as ss
from pkg_test.misc_test import EmptyI
"""
# a python module that causes slightly different behaviour in
# modulefinder.py
python_module_text = """\
#! /usr/bin/python
class Foo(object):
def run(self):
import __main__
"""
smf_fmris = {}
smf_known_deps = {}
smf_fmris["service_single"] = [ \
"svc:/application/pkg5test/service-default",
"svc:/application/pkg5test/service-default:default" ]
smf_known_deps["svc:/application/pkg5test/service-default"] = \
["svc:/application/pkg5test/delivered-many"]
smf_known_deps["svc:/application/pkg5test/service-default:default"] = \
["svc:/application/pkg5test/delivered-many"]
smf_manifest_text = {}
smf_manifest_text["service_single"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='service-default'>
<!-- we deliver:
svc:/application/pkg5test/service-default
(deps: svc:/application/pkg5test/delivered-many)
svc:/application/pkg5test/service-default:default
-->
<service
name='application/pkg5test/service-default'
type='service'
version='0.1'>
<dependency
name="delivered-service"
grouping="require_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/delivered-many" />
</dependency>
<!-- We should not pick this up as an IPS dependency -->
<dependency
name="my-path"
grouping="require_all"
restart_on="none"
type="path">
<service_fmri value="/var/foo/something.conf" />
</dependency>
<create_default_instance enabled='true' />
<single_instance/>
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
</service>
</service_bundle>
"""
smf_fmris["service_many"] = [ \
"svc:/application/pkg5test/service-many",
"svc:/application/pkg5test/service-many:default",
"svc:/application/pkg5test/service-many:one",
"svc:/application/pkg5test/service-many:two" ]
smf_known_deps["svc:/application/pkg5test/service-many"] = \
["svc:/application/pkg5test/foreign-many"]
smf_known_deps["svc:/application/pkg5test/service-many:default"] = \
["svc:/application/pkg5test/foreign-many"]
smf_known_deps["svc:/application/pkg5test/service-many:one"] = \
["svc:/application/pkg5test/foreign-many",
"svc:/application/pkg5test/foreign-many:default"]
smf_known_deps["svc:/application/pkg5test/service-many:two"] = \
["svc:/application/pkg5test/foreign-many"]
smf_manifest_text["service_many"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='pkg5test-many-instances'>
<!-- we deliver:
svc:/application/pkg5test/service-many
(deps: svc:/application/pkg5test/foreign-many
svc:/application/pkg5test/foreign-opt (not required))
svc:/application/pkg5test/service-many:default
svc:/application/pkg5test/service-many:one
(deps: svc:/application/pkg5test/foreign-opt:default (not required)
svc:/application/pkg5test/foreign-many:default)
svc:/application/pkg5test/service-many:two
-->
<service
name='application/pkg5test/service-many'
type='service'
version='0.1'>
<!-- a dependency a different package delivers -->
<dependency
name="foreign-service"
grouping="require_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/foreign-many" />
</dependency>
<!-- pkg(5) shouldn't see this as a dependency -->
<dependency
name="optional-service"
grouping="optional_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/foreign-opt" />
</dependency>
<create_default_instance enabled='true' />
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='0'>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='0'>
</exec_method>
<instance name='one' enabled='false' >
<dependency
name="optional-service"
grouping="require_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/foreign-many:default" />
</dependency>
</instance>
<!-- no dependencies here -->
<instance name='two' enabled='false' />
</service>
</service_bundle>
"""
smf_fmris["service_unknown"] = [ \
"svc:/application/pkg5test/service-unknown",
"svc:/application/pkg5test/service-unknown:default",
"svc:/application/pkg5test/service-unknown:one"]
smf_known_deps["svc:/application/pkg5test/service-unknown"] = \
["svc:/application/pkg5test/delivered-many",
"svc:/application/pkg5test/unknown-service"]
smf_known_deps["svc:/application/pkg5test/service-unknown:default"] = \
["svc:/application/pkg5test/delivered-many",
"svc:/application/pkg5test/unknown-service"]
smf_known_deps["svc:/application/pkg5test/service-unknown:one"] = \
["svc:/application/pkg5test/delivered-many",
"svc:/application/pkg5test/unknown-service",
"svc:/application/pkg5test/another-unknown:default"]
smf_manifest_text["service_unknown"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='service-unknown'>
<!-- we deliver:
svc:/application/pkg5test/service-unknown
(deps: svc:/application/pkg5test/delivered-many
svc:/application/pkg5test/unknown-service
svc:/application/pkg5test/service-unknown:default
(deps: svc:/application/pkg5test/delivered-many
svc:/application/pkg5test/unknown-service)
svc:/application/pkg5test/service-unknown:one
(deps: svc:/application/pkg5test/delivered-many
svc:/application/pkg5test/unknown-service
svc:/application/pkg5test/another-unknown:default)
-->
<service
name='application/pkg5test/service-unknown'
type='service'
version='0.1'>
<dependency
name="delivered-service"
grouping="require_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/delivered-many" />
</dependency>
<!-- pkg(5) should throw an error here, as we don't deliver this
service, nor does any other package in our test suite -->
<dependency
name="unknown-service"
grouping="require_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/unknown-service" />
</dependency>
<create_default_instance enabled='true' />
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<instance name='one' enabled='false' >
<!-- pkg(5) should throw an error being unable to resolve this -->
<dependency
name="another"
grouping="require_all"
restart_on="none"
type="service">
<service_fmri value="svc:/application/pkg5test/another-unknown:default" />
</dependency>
</instance>
</service>
</service_bundle>
"""
smf_fmris["delivered_many_nodeps"] = [ \
"svc:/application/pkg5test/delivered-many",
"svc:/application/pkg5test/delivered-many:nodeps",
"svc:/application/pkg5test/delivered-many:nodeps1" ]
smf_known_deps["svc:/application/pkg5test/delivered-many"] = []
smf_known_deps["svc:/application/pkg5test/delivered-many:nodeps"] = []
smf_known_deps["svc:/application/pkg5test/delivered-many:nodeps1"] = []
smf_manifest_text["delivered_many_nodeps"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='default-service-many'>
<!-- we deliver
svc:/application/pkg5test/delivered-many
svc:/application/pkg5test/delivered-many:nodeps
svc:/application/pkg5test/delivered-many:nodeps1
None of these services or instances declare any dependencies.
-->
<service
name='application/pkg5test/delivered-many'
type='service'
version='0.1'>
<single_instance />
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<instance name="nodeps" enabled="true" />
<instance name='nodeps1' enabled='false' />
</service>
</service_bundle>
"""
smf_fmris["foreign_single_nodeps"] = [ \
"svc:/application/pkg5test/foreign-single",
"svc:/application/pkg5test/foreign-single:nodeps" ]
smf_known_deps["svc:/application/pkg5test/foreign-single"] = []
smf_known_deps["svc:/application/pkg5test/foreign-single:nodeps"] = []
smf_manifest_text["foreign_single_nodeps"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='SUNWcsr:cron'>
<!-- we deliver
svc:/application/pkg5test/foreign-single
svc:/application/pkg5test/foreign-single:nodeps
None of these services or instances declare any dependencies.
-->
<service
name='application/pkg5test/foreign-single'
type='service'
version='0.1'>
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<instance name='nodeps' enabled='false' />
</service>
</service_bundle>
"""
smf_fmris["foreign_many_nodeps"] = [ \
"svc:/application/pkg5test/foreign-many",
"svc:/application/pkg5test/foreign-many:default",
"svc:/application/pkg5test/foreign-many:nodeps",
"svc:/application/pkg5test/foreign-opt",
"svc:/application/pkg5test/foreign-opt:nodeps" ]
smf_known_deps["svc:/application/pkg5test/foreign-many"] = []
smf_known_deps["svc:/application/pkg5test/foreign-many:default"] = []
smf_known_deps["svc:/application/pkg5test/foreign-many:nodeps"] = []
smf_known_deps["svc:/application/pkg5test/foreign-opt"] = []
smf_known_deps["svc:/application/pkg5test/foreign-opt:nodeps"] = []
smf_manifest_text["foreign_many_nodeps"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='foreign-many-instances'>
<!-- we deliver
svc:/application/pkg5test/foreign-many
svc:/application/pkg5test/foreign-many:default
svc:/application/pkg5test/foreign-many:nodeps
svc:/application/pkg5test/foreign-opt
svc:/application/pkg5test/foreign-opt:nodeps
Note that this manifest contains two <service> elements.
None of these services or instances declare any dependencies.
-->
<service
name='application/pkg5test/foreign-many'
type='service'
version='0.1'>
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<!-- intentionally declaring the default service, as opposed to using
create_default_service - to test smf manifest parsing code in pkg5 -->
<instance name='default' enabled='false' />
<instance name='nodeps' enabled='false' />
</service>
<service
name='application/pkg5test/foreign-opt'
type='service'
version='0.1'>
<single_instance />
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<exec_method
type='method'
name='stop'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<instance name='nodeps' enabled='false' />
</service>
</service_bundle>
"""
smf_manifest_text["broken"] = \
"""<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type='manifest' name='broken-service'>
<!-- we deliver nothing - this service manifest is intentionally broken
-->
<service <<> This is the broken line
name='application/pkg5test/brokenservice'
type='service'
version='0.1'>
<single_instance />
<exec_method
type='method'
name='start'
exec=':true'
timeout_seconds='60'>
<method_context>
<method_credential user='root' group='root' />
</method_context>
</exec_method>
<instance name='default' enabled='false' />
</service>
</service_bundle>
"""
int_smf_manf = """\
file NOHASH group=sys mode=0644 owner=root path=%(service_single)s
file NOHASH group=sys mode=0644 owner=root path=%(delivered_many_nodeps)s
""" % paths
ext_smf_manf = """\
file NOHASH group=sys mode=0644 owner=root path=%(service_many)s
file NOHASH group=sys mode=0644 owner=root path=%(foreign_single_nodeps)s
""" % paths
broken_smf_manf = """\
file NOHASH group=sys mode=0644 owner=root path=%(broken)s
file NOHASH group=sys mode=0644 owner=root path=%(delivered_many_nodeps)s
file NOHASH group=sys mode=0644 owner=root path=%(service_single)s
""" % paths
faildeps_smf_manf = """\
file NOHASH group=sys mode=0644 owner=root path=%(delivered_many_nodeps)s
file NOHASH group=sys mode=0644 owner=root path=%(service_single)s
file NOHASH group=sys mode=0644 owner=root path=%(service_unknown)s
""" % paths
script_text = "#!/usr/bin/ksh -p\n"
def setUp(self):
pkg5unittest.Pkg5TestCase.setUp(self)
self.proto_dir = os.path.join(self.test_root, "proto")
os.makedirs(self.proto_dir)
def make_proto_text_file(self, path, contents=""):
self.make_misc_files({ path: contents }, prefix="proto")
def make_python_test_files(self, py_version):
pdir = "usr/lib/python%s/vendor-packages" % py_version
self.make_proto_text_file("%s/pkg_test/__init__.py" % pdir,
"#!/usr/bin/python\n")
self.make_proto_text_file(
"%s/pkg_test/indexer_test/__init__.py" % pdir,
"#!/usr/bin/python")
self.make_proto_text_file("%s/cProfile.py" % pdir,
self.python_module_text)
def make_smf_test_files(self):
for manifest in self.smf_paths.keys():
self.make_proto_text_file(self.paths[manifest],
self.smf_manifest_text[manifest])
def make_elf(self, final_path, static=False):
out_file = os.path.join(self.proto_dir, final_path)
opts = []
# In some cases we want to generate an elf binary with no
# dependencies of its own. We use -c (supress linking) for
# this purpose.
if static:
opts.extend(["-c"])
self.c_compile("int main(){}\n", opts, out_file)
return out_file[len(self.proto_dir)+1:]
def __path_to_key(self, path):
if path == self.paths["libc_path"]:
return ((os.path.basename(path),), tuple([
p.lstrip("/") for p in elf.default_run_paths
]))
return ((os.path.basename(path),), (os.path.dirname(path),))
def test_ext_hardlink(self):
"""Check that a hardlink with a target outside the package is
reported as a dependency."""
def _check_results(res):
ds, es, ms, pkg_attrs = res
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 3)
ans = set(["usr/foo", "usr/bar"])
for d in ds:
self.assert_(d.dep_vars.is_satisfied())
self.assert_(d.is_error())
if d.dep_key() == self.__path_to_key(
self.paths["syslog_path"]):
self.assert_(
d.action.attrs["path"] in ans)
ans.remove(d.action.attrs["path"])
else:
self.assertEqual(d.dep_key(),
self.__path_to_key(
self.paths["authlog_path"]))
self.assertEqual(
d.action.attrs["path"], "baz")
t_path = self.make_manifest(self.ext_hardlink_manf)
_check_results(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False))
_check_results(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [],
remove_internal_deps=False, convert=False))
def test_int_hardlink(self):
"""Check that a hardlink with a target inside the package is
not reported as a dependency, unless the flag to show internal
dependencies is set."""
t_path = self.make_manifest(self.int_hardlink_manf)
self.make_proto_text_file(self.paths["syslog_path"])
ds, es, ms, pkg_attrs = \
dependencies.list_implicit_deps(t_path, [self.proto_dir],
{}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assert_(len(ms) == 1)
self.assert_(len(ds) == 0)
# Check that internal dependencies are as expected.
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(len(ms), 1)
self.assertEqual(len(ds), 1)
d = ds[0]
self.assert_(d.dep_vars.is_satisfied())
self.assert_(d.is_error())
self.assertEqual(d.dep_key(), self.__path_to_key(
self.paths["syslog_path"]))
self.assertEqual(d.action.attrs["path"], "usr/foo")
def test_ext_script(self):
"""Check that a file that starts with #! and references a file
outside its package is reported as a dependency."""
def _check_res(res):
ds, es, ms, pkg_attrs = res
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 1)
d = ds[0]
self.assert_(d.is_error())
self.assert_(d.dep_vars.is_satisfied())
self.assertEqual(d.dep_key(),
self.__path_to_key(self.paths["ksh_path"]))
self.assertEqual(d.action.attrs["path"],
self.paths["script_path"])
t_path = self.make_manifest(self.ext_script_manf)
self.make_proto_text_file(self.paths["script_path"],
self.script_text)
_check_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False))
_check_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False))
def test_int_script(self):
"""Check that a file that starts with #! and references a file
inside its package is not reported as a dependency unless
the flag to show internal dependencies is set."""
t_path = self.make_manifest(self.int_script_manf)
self.make_elf(self.paths["ksh_path"])
self.make_proto_text_file(self.paths["script_path"],
self.script_text)
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 1)
d = ds[0]
self.assert_(d.is_error())
self.assert_(d.dep_vars.is_satisfied())
self.assertEqual(d.base_names[0], "libc.so.1")
self.assertEqual(set(d.run_paths), set(["lib",
"usr/lib"]))
# Check that internal dependencies are as expected.
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
self.assertEqual(len(ds), 2)
for d in ds:
self.assert_(d.is_error())
self.assert_(d.dep_vars.is_satisfied())
if d.dep_key() == self.__path_to_key(
self.paths["ksh_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["script_path"])
elif d.dep_key() == self.__path_to_key(
self.paths["libc_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["ksh_path"])
else:
raise RuntimeError("Unexpected "
"dependency path:%s" % d)
def test_ext_elf(self):
"""Check that an elf file that requires a library outside its
package is reported as a dependency."""
def _check_res(res):
ds, es, ms, pkg_attrs = res
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 1)
d = ds[0]
self.assert_(d.is_error())
self.assert_(d.dep_vars.is_satisfied())
self.assertEqual(d.base_names[0], "libc.so.1")
self.assertEqual(set(d.run_paths),
set(["lib", "usr/lib"]))
self.assertEqual(d.dep_key(),
self.__path_to_key(self.paths["libc_path"]))
self.assertEqual(
d.action.attrs["path"],
self.paths["curses_path"])
t_path = self.make_manifest(self.ext_elf_manf)
self.make_elf(self.paths["curses_path"])
_check_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False))
_check_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False))
def test_int_elf(self):
"""Check that an elf file that requires a library inside its
package is not reported as a dependency unless the flag to show
internal dependencies is set."""
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assertEqual(len(ds), 1)
d = ds[0]
self.assert_(d.is_error())
self.assert_(d.dep_vars.is_satisfied())
self.assertEqual(d.base_names[0], "libc.so.1")
self.assertEqual(set(d.run_paths),
set(["lib", "usr/lib"]))
self.assertEqual(d.dep_key(),
self.__path_to_key(self.paths["libc_path"]))
self.assertEqual(d.action.attrs["path"],
self.paths["curses_path"])
t_path = self.make_manifest(self.int_elf_manf)
self.make_elf(self.paths["curses_path"])
self.make_elf(self.paths["libc_path"], static=True)
d_map, es, ms, pkg_attrs = dependencies.list_implicit_deps(
t_path, [self.proto_dir], {}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(d_map) == 0)
# Check that internal dependencies are as expected.
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False))
def test_ext_python_dep(self):
"""Check that a python file that imports a module outside its
package is reported as a dependency."""
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo"]
mod_names = ["foobar", "misc_test", "os",
"search_storage"]
pkg_names = ["indexer_test", "pkg", "pkg_test"]
expected_deps = set([("python",)] +
[tuple(sorted([
"%s%s" % (n,s) for s in mod_suffs
]))
for n in mod_names] +
[("%s/__init__.py" % n,) for n in pkg_names])
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
for d in ds:
self.assert_(d.is_error())
if d.dep_vars is None:
raise RuntimeError("This dep had "
"depvars of None:%s" % d)
self.assert_(d.dep_vars.is_satisfied())
if not d.dep_key()[0] in expected_deps:
raise RuntimeError("Got this "
"unexpected dep:%s\n\nd:%s" %
(d.dep_key()[0], d))
expected_deps.remove(d.dep_key()[0])
self.assertEqual(d.action.attrs["path"],
self.paths["indexer_path"])
if expected_deps:
raise RuntimeError("Couldn't find these "
"dependencies:\n" + "\n".join(
[str(s) for s in sorted(expected_deps)]))
self.__debug = True
t_path = self.make_manifest(self.ext_python_manf)
self.make_python_test_files(2.6)
self.make_proto_text_file(self.paths["indexer_path"],
self.python_text)
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False))
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False))
def test_ext_python_abs_import_dep(self):
"""Check that a python file that uses absolute imports a module
is handled correctly."""
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo"]
mod_names = ["foobar", "os", "search_storage"]
pkg_names = ["indexer_test", "pkg", "pkg_test"]
expected_deps = set([("python",)] +
[tuple(sorted([
"%s%s" % (n,s) for s in mod_suffs
]))
for n in mod_names] +
[("%s/__init__.py" % n,) for n in pkg_names])
if len(es) != 1:
raise RuntimeError("Expected exactly 1 error, "
"got:%\n" + "\n".join([str(s) for s in es]))
if es[0].name != "misc_test":
raise RuntimeError("Didn't get the expected "
"error. Error found was:%s" % es[0])
self.assertEqual(ms, {})
for d in ds:
self.assert_(d.is_error())
if d.dep_vars is None:
raise RuntimeError("This dep had "
"depvars of None:%s" % d)
self.assert_(d.dep_vars.is_satisfied())
if not d.dep_key()[0] in expected_deps:
raise RuntimeError("Got this "
"unexpected dep:%s\n\nd:%s" %
(d.dep_key()[0], d))
expected_deps.remove(d.dep_key()[0])
self.assertEqual(d.action.attrs["path"],
self.paths["indexer_path"])
if expected_deps:
raise RuntimeError("Couldn't find these "
"dependencies:\n" + "\n".join(
[str(s) for s in sorted(expected_deps)]))
self.__debug = True
t_path = self.make_manifest(self.ext_python_manf)
self.make_python_test_files(2.6)
# Check that absolute imports still work.
self.make_proto_text_file(self.paths["indexer_path"],
self.python_abs_text)
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False))
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False))
def test_ext_python_pkg_dep(self):
"""Check that a python file that is the __init__.py file for a
package is handled correctly."""
def _check_all_res(res):
ds, es, ms, pkg_attrs = res
mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo"]
mod_names = ["foobar", "misc_test", "os",
"search_storage"]
pkg_names = ["indexer_test", "pkg", "pkg_test"]
expected_deps = set([("python",)] +
[tuple(sorted([
"%s%s" % (n,s) for s in mod_suffs
]))
for n in mod_names] +
[("%s/__init__.py" % n,) for n in pkg_names])
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
for d in ds:
self.assert_(d.is_error())
if d.dep_vars is None:
raise RuntimeError("This dep had "
"depvars of None:%s" % d)
self.assert_(d.dep_vars.is_satisfied())
if not d.dep_key()[0] in expected_deps:
raise RuntimeError("Got this "
"unexpected dep:%s\n\nd:%s" %
(d.dep_key()[0], d))
expected_deps.remove(d.dep_key()[0])
self.assertEqual(d.action.attrs["path"],
self.paths["pkg_path"])
if expected_deps:
raise RuntimeError("Couldn't find these "
"dependencies:\n" + "\n".join(
[str(s) for s in sorted(expected_deps)]))
self.__debug = True
t_path = self.make_manifest(self.ext_python_pkg_manf)
self.make_python_test_files(2.6)
self.make_proto_text_file(self.paths["pkg_path"],
self.python_text)
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False))
_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False))
def test_python_imp_main(self):
"""Ensure we can generate a dependency from a python module
known to cause different behaviour in modulefinder, where
we try to import __main__"""
t_path = self.make_manifest(self.python_mod_manf)
self.make_python_test_files(2.4)
self.make_python_test_files(2.6)
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
self.assert_(es != 0, "Unexpected errors reported: %s" % es)
self.assert_(ds != 2, "Unexpected deps reported: %s" % ds)
def test_variants_1(self):
"""Test that a file which satisfies a dependency only under a
certain set of variants results in the dependency being reported
for the other set of variants."""
t_path = self.make_manifest(self.variant_manf_1)
self.make_proto_text_file(self.paths["script_path"],
self.script_text)
self.make_elf(self.paths["ksh_path"])
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 2)
for d in ds:
self.assert_(d.is_error())
if d.dep_key() == self.__path_to_key(
self.paths["ksh_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["script_path"])
expected_not_sat = set([
frozenset([("variant.arch", "bar")]),
frozenset([("variant.arch", "baz")])])
expected_sat = set([
frozenset([("variant.arch", "foo")])])
self.assertEqual(expected_sat,
d.dep_vars.sat_set)
self.assertEqual(expected_not_sat,
d.dep_vars.not_sat_set)
elif d.dep_key() == self.__path_to_key(
self.paths["libc_path"]):
self.assertEqual(
d.action.attrs["path"],
self.paths["ksh_path"])
expected_not_sat = set([
frozenset([("variant.arch", "foo")])])
expected_sat = set()
self.assertEqual(expected_sat,
d.dep_vars.sat_set)
self.assertEqual(expected_not_sat,
d.dep_vars.not_sat_set)
else:
raise RuntimeError("Unexpected "
"dependency path:%s" % (d.dep_key(),))
def test_variants_2(self):
"""Test that when the variants of the action with the dependency
and the action satisfying the dependency share the same
dependency, an external dependency is not reported."""
t_path = self.make_manifest(self.variant_manf_2)
self.make_proto_text_file(self.paths["script_path"],
self.script_text)
self.make_elf(self.paths["ksh_path"])
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 1)
d = ds[0]
self.assert_(d.is_error())
expected_not_sat = set([frozenset([("variant.arch", "foo")])])
expected_sat = set()
self.assertEqual(expected_sat, d.dep_vars.sat_set)
self.assertEqual(expected_not_sat, d.dep_vars.not_sat_set)
self.assertEqual(d.base_names[0], "libc.so.1")
self.assertEqual(set(d.run_paths), set(["lib", "usr/lib"]))
# Check that internal dependencies are as expected.
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 2)
for d in ds:
self.assert_(d.is_error())
# Because not removing internal dependencies means that
# no resolution of their variants happens, both
# dependencies have their variants as unsatisfied.
expected_not_sat = set([
frozenset([("variant.arch", "foo")])])
expected_sat = set()
self.assertEqual(expected_sat, d.dep_vars.sat_set)
self.assertEqual(expected_not_sat,
d.dep_vars.not_sat_set)
if d.dep_key() == self.__path_to_key(
self.paths["ksh_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["script_path"])
elif d.dep_key() == self.__path_to_key(
self.paths["libc_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["ksh_path"])
else:
raise RuntimeError(
"Unexpected dependency path:%s" %
(d.dep_key(),))
def test_variants_3(self):
"""Test that when the action with the dependency is tagged with
a different variant than the action which could satisfy it, it's
reported as an external dependency."""
t_path = self.make_manifest(self.variant_manf_3)
self.make_proto_text_file(self.paths["script_path"],
self.script_text)
self.make_elf(self.paths["ksh_path"])
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 2)
for d in ds:
self.assert_(d.is_error())
if d.dep_key() == self.__path_to_key(
self.paths["ksh_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["script_path"])
expected_not_sat = set([
frozenset([("variant.arch", "bar")])])
expected_sat = set()
self.assertEqual(expected_sat,
d.dep_vars.sat_set)
self.assertEqual(expected_not_sat,
d.dep_vars.not_sat_set)
elif d.dep_key() == self.__path_to_key(
self.paths["libc_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["ksh_path"])
expected_not_sat = set([
frozenset([("variant.arch", "foo")])])
expected_sat = set()
self.assertEqual(expected_sat,
d.dep_vars.sat_set)
self.assertEqual(expected_not_sat,
d.dep_vars.not_sat_set)
else:
raise RuntimeError("Unexpected "
"dependency path:%s" % (d.dep_key(),))
def test_variants_4(self):
"""Test that an action with a variant that depends on a
delivered action also tagged with that variant, but not with a
package-level variant is reported as an internal dependency, not
an external one."""
t_path = self.make_manifest(self.variant_manf_4)
self.make_proto_text_file(self.paths["script_path"],
self.script_text)
self.make_elf(self.paths["ksh_path"])
# Check that we only report a single external dependency
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(ds) == 1)
d = ds[0]
self.assert_(d.is_error())
expected_not_sat = set([frozenset([
("variant.arch", "foo"),
("variant.opensolaris.zone", "global")])])
expected_sat = set()
self.assertEqual(expected_sat, d.dep_vars.sat_set)
self.assertEqual(expected_not_sat, d.dep_vars.not_sat_set)
self.assertEqual(d.base_names[0], "libc.so.1")
self.assertEqual(set(d.run_paths), set(["lib", "usr/lib"]))
# Check that internal dependencies are as expected.
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assertEqual(pkg_attrs, {})
self.assert_(len(ds) == 2)
for d in ds:
self.assert_(d.is_error())
# Because not removing internal dependencies means that
# no resolution of their variants happens, both
# dependencies have their variants as unsatisfied.
expected_not_sat = set([frozenset([
("variant.arch", "foo"),
("variant.opensolaris.zone", "global")])])
expected_sat = set()
self.assertEqual(expected_sat, d.dep_vars.sat_set)
self.assertEqual(expected_not_sat,
d.dep_vars.not_sat_set)
if d.dep_key() == self.__path_to_key(
self.paths["ksh_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["script_path"])
elif d.dep_key() == self.__path_to_key(
self.paths["libc_path"]):
self.assertEqual(d.action.attrs["path"],
self.paths["ksh_path"])
else:
raise RuntimeError(
"Unexpected dependency path:%s" % \
(d.dep_key(),))
def test_symlinks(self):
"""Test that a file is recognized as delivered when a symlink
is involved."""
usr_path = os.path.join(self.proto_dir, "usr")
hardlink_path = os.path.join(usr_path, "foo")
bar_path = os.path.join(self.proto_dir, "bar")
file_path = os.path.join(bar_path, "syslog")
var_path = os.path.join(self.proto_dir, "var")
symlink_loc = os.path.join(var_path, "log")
hardlink_target = os.path.join(usr_path,
"../var/log/syslog")
os.mkdir(usr_path)
os.mkdir(bar_path)
os.mkdir(var_path)
fh = open(file_path, "w")
fh.close()
os.symlink(bar_path, symlink_loc)
os.link(hardlink_target, hardlink_path)
t_path = self.make_manifest(
self.int_hardlink_manf_test_symlink)
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
def test_str_methods(self):
"""Test the str methods of objects in the flavor space."""
str(base.MissingFile("fp"))
str(elf.BadElfFile("fp", "ex"))
str(elf.UnsupportedDynamicToken("/proto_path", "/install",
"run_path", "tok"))
str(py.PythonModuleMissingPath("foo", "bar"))
str(py.PythonMismatchedVersion("2.4", "2.6", "foo", "bar"))
str(py.PythonSubprocessError(2, "foo", "bar"))
str(py.PythonSubprocessBadLine("cmd", ["l1", "l2"]))
mi = dlmf.ModuleInfo("name", ["/d1", "/d2"])
str(mi)
mi.make_package()
str(mi)
def test_multi_proto_dirs(self):
"""Check that analysis works correctly when multiple proto_dirs
are given."""
def _check_all_res(res):
ds, es, ms = res
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assertEqual(len(ds), 1)
d = ds[0]
self.assert_(d.is_error())
self.assert_(d.dep_vars.is_satisfied())
self.assertEqual(d.base_names[0], "libc.so.1")
self.assertEqual(set(d.run_paths),
set(["lib", "usr/lib"]))
self.assertEqual(d.dep_key(),
self.__path_to_key(self.paths["libc_path"]))
self.assertEqual(d.action.attrs["path"],
self.paths["curses_path"])
t_path = self.make_manifest(self.int_elf_manf)
self.make_elf(os.path.join("foo", self.paths["curses_path"]))
self.make_elf(self.paths["libc_path"], static=True)
# This should fail because the "foo" directory is not given
# as a proto_dir.
d_map, es, ms, pkg_attrs = dependencies.list_implicit_deps(
t_path, [self.proto_dir], {}, [], convert=False)
if len(es) != 1:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
if es[0].file_path != \
os.path.join(self.proto_dir, self.paths["curses_path"]):
raise RuntimeError("Wrong file was found missing:\n%s" %
es[0])
self.assertEqual(ms, {})
self.assert_(len(d_map) == 0)
# This should work since the "foo" directory has been added to
# the list of proto_dirs to use.
d_map, es, ms, pkg_attrs = dependencies.list_implicit_deps(
t_path, [self.proto_dir,
os.path.join(self.proto_dir, "foo")], {}, [], convert=False)
if es:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(d_map) == 0)
# This should be different because the empty text file
# is found before the binary file.
self.make_proto_text_file(self.paths["curses_path"])
d_map, es, ms, pkg_attrs = dependencies.list_implicit_deps(
t_path, [self.proto_dir,
os.path.join(self.proto_dir, "foo")], {}, [],
remove_internal_deps=False, convert=False)
if es:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
if len(ms) != 1:
raise RuntimeError("Didn't get expected types of "
"missing files:\n%s" % ms)
self.assertEqual(ms.keys()[0], "empty file")
self.assert_(len(d_map) == 0)
# This should find the binary file first and thus produce
# a depend action.
d_map, es, ms, pkg_attrs = dependencies.list_implicit_deps(
t_path, [os.path.join(self.proto_dir, "foo"),
self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
if es:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
self.assert_(len(d_map) == 1)
# Check alternative proto_dirs with hardlinks.
t_path = self.make_manifest(self.int_hardlink_manf)
self.make_proto_text_file(os.path.join("foo",
self.paths["syslog_path"]))
# This test should fail because "foo" is not included in the
# list of proto_dirs.
ds, es, ms, pkg_attrs = \
dependencies.list_implicit_deps(t_path, [self.proto_dir],
{}, [], convert=False)
if len(es) != 1:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
if es[0].file_path != \
os.path.join(self.proto_dir, self.paths["syslog_path"]):
raise RuntimeError("Wrong file was found missing:\n%s" %
es[0])
self.assert_(len(ms) == 0)
self.assert_(len(ds) == 1)
# This test should pass because the needed directory has been
# added to the list of proto_dirs.
ds, es, ms, pkg_attrs = \
dependencies.list_implicit_deps(t_path,
[self.proto_dir, os.path.join(self.proto_dir, "foo")],
{}, [], convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assert_(len(ms) == 1)
self.assert_(len(ds) == 0)
# Check alternative proto_dirs work with python files and
# scripts.
def _py_check_all_res(res):
ds, es, ms, pkg_attrs = res
mod_suffs = ["/__init__.py", ".py", ".pyc", ".pyo"]
mod_names = ["foobar", "misc_test", "os",
"search_storage"]
pkg_names = ["indexer_test", "pkg", "pkg_test"]
expected_deps = set([("python",)] +
[tuple(sorted([
"%s%s" % (n,s) for s in mod_suffs
]))
for n in mod_names] +
[("%s/__init__.py" % n,) for n in pkg_names])
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assertEqual(ms, {})
for d in ds:
self.assert_(d.is_error())
if d.dep_vars is None:
raise RuntimeError("This dep had "
"depvars of None:%s" % d)
self.assert_(d.dep_vars.is_satisfied())
if not d.dep_key()[0] in expected_deps:
raise RuntimeError("Got this "
"unexpected dep:%s\n\nd:%s" %
(d.dep_key()[0], d))
expected_deps.remove(d.dep_key()[0])
self.assertEqual(d.action.attrs["path"],
self.paths["indexer_path"])
if expected_deps:
raise RuntimeError("Couldn't find these "
"dependencies:\n" + "\n".join(
[str(s) for s in sorted(expected_deps)]))
self.__debug = True
t_path = self.make_manifest(self.ext_python_manf)
self.make_proto_text_file(
os.path.join("d5", self.paths["indexer_path"]),
self.python_text)
# This should have an error because it cannot find the file
# needed.
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], convert=False)
if len(es) != 1:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
if es[0].file_path != \
os.path.join(self.proto_dir, self.paths["indexer_path"]):
raise RuntimeError("Wrong file was found missing:\n%s" %
es[0])
self.assertEqual(len(ds), 0)
self.assertEqual(len(ms), 0)
# Because d5 is in the list of proto dirs, this test should work
# normally.
_py_check_all_res(dependencies.list_implicit_deps(t_path,
[self.proto_dir, os.path.join(self.proto_dir, "d5")], {},
[], convert=False))
def test_smf_manifest_parse(self):
""" We parse valid SMF manifests returning instance
and dependency info."""
for manifest in self.smf_paths.keys():
self.make_proto_text_file(self.paths[manifest],
self.smf_manifest_text[manifest])
# This should not parse, returning empty lists
if manifest == "broken":
instances, deps = smf.parse_smf_manifest(
self.proto_dir+ "/" + self.paths[manifest])
self.assertEqual(instances, None)
self.assertEqual(deps, None)
continue
# Ensuring each manifest can be parsed
# and we detect declared dependencies and
# FMRIs according to those hardcoded in the test
instances, deps = smf.parse_smf_manifest(
self.proto_dir+ "/" + self.paths[manifest])
for fmri in instances:
for dep in self.smf_known_deps[fmri]:
if dep not in deps[fmri]:
self.assert_(False,
"%s not found in "
"dependencies for %s" %
(dep, manifest))
expected = len(self.smf_known_deps[fmri])
actual = len(deps[fmri])
self.assertEqual(expected, actual,
"expected number of deps (%s) != "
"actual (%s) for %s"
% (expected, actual, fmri))
def check_smf_fmris(self, pkg_attrs, expected, manifest_name):
""" Given a list of expected SMF FMRIs, verify that each is
present in the provided pkg_attrs dictionary. Errors are
reported in an assertion message that includes manifest_name."""
self.assert_(pkg_attrs.has_key("opensolaris.smf.fmri"),
"Missing opensolaris.smf.fmri key for %s" % manifest_name)
found = len(pkg_attrs["opensolaris.smf.fmri"])
self.assertEqual(found, len(expected),
"Wrong no. of SMF instances/services found for %s: expected"
" %s got %s" % (manifest_name, len(expected), found))
for fmri in expected:
self.assert_(
fmri in pkg_attrs["opensolaris.smf.fmri"],
"%s not in list of SMF instances/services "
"from %s" % (fmri, manifest_name))
def print_deps(self, deps):
for dep in deps:
print dep.base_names
def test_int_smf_manifest(self):
"""We identify SMF dependencies delivered in the same package"""
t_path = self.make_manifest(self.int_smf_manf)
self.make_smf_test_files()
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assert_(len(ds) == 1, "Expected 1 dependency, got %s" %
len(ds))
d = ds[0]
# verify we have identified the one internal file we depend on
actual = d.manifest.replace(self.proto_dir + "/", "")
expected = self.paths["delivered_many_nodeps"]
self.assertEqual(actual, expected,
"Expected dependency path %s, got %s" % (actual, expected))
self.check_smf_fmris(pkg_attrs,
self.smf_fmris["service_single"] +
self.smf_fmris["delivered_many_nodeps"],
"int_smf_manf")
# verify that removing internal dependencies works as expected
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=True,
convert=False)
self.assert_(len(ds) == 0, "Expected 0 dependencies, got %s" %
len(ds))
def test_ext_smf_manifest(self):
"""We identify SMF dependencies delivered in a different
package"""
t_path = self.make_manifest(self.ext_smf_manf)
self.make_smf_test_files()
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
self.assert_(len(ds) == 1, "Expected 1 dependency, got %s" %
len(ds))
# verify we have identified the one external file we depend on
actual = ds[0].manifest.replace(self.proto_dir + "/", "")
expected = self.paths["foreign_many_nodeps"]
self.assertEqual(actual, expected ,
"Expected dependency path %s, got %s" % (actual, expected))
self.check_smf_fmris(pkg_attrs,
self.smf_fmris["service_many"] +
self.smf_fmris["foreign_single_nodeps"],
"ext_smf_manf")
def test_broken_manifest(self):
"""We report errors when dealing with a broken SMF manifest."""
# as it happens, file(1) isn't good at spotting broken
# XML documents, it only sniffs the header - so this file
# gets reported as an 'XML document' despite it being invalid
# XML.
t_path = self.make_manifest(self.broken_smf_manf)
self.make_smf_test_files()
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
self.assertEqual(len(ms), 1, "No unknown files reported during "
"analysis")
if "XML document" not in ms:
self.assert_(False, "Broken SMF manifest file not"
" declared")
broken_path = os.path.join(self.proto_dir, self.paths["broken"])
self.assertEqual(ms["XML document"], broken_path,
"Did not detect broken SMF manifest file: %s != %s" % (
broken_path, ms["XML document"]))
# We should still be able to resolve the other dependencies
# though and it's important to check that the one broken SMF
# manifest file didn't break the rest of the SMF manifest
# backend. This has been implicitly tested in other tests,
# as the broken file is always installed in the manifest
# location.
if es != []:
raise RuntimeError("Got errors in results:" +
"\n".join([str(s) for s in es]))
# our dependency comes from service_single depending on
# delivered_many
self.assert_(len(ds) == 1, "Expected 1 dependency, got %s" %
len(ds))
d = ds[0]
# verify we have identified the one internal file we depend on
actual = d.manifest.replace(self.proto_dir + "/", "")
expected = self.paths["delivered_many_nodeps"]
self.assertEqual(actual, expected ,
"Expected dependency path %s, got %s" % (actual, expected))
self.check_smf_fmris(pkg_attrs,
self.smf_fmris["service_single"] +
self.smf_fmris["delivered_many_nodeps"],
"broken_smf_manf")
def test_faildeps_smf_manifest(self):
"""We report failed attempts to resolve dependencies"""
t_path = self.make_manifest(self.faildeps_smf_manf)
self.make_smf_test_files()
ds, es, ms, pkg_attrs = dependencies.list_implicit_deps(t_path,
[self.proto_dir], {}, [], remove_internal_deps=False,
convert=False)
self.assert_(len(es) == 3,
"Detected %s error(s), expected 3" % len(es))
# our two dependencies come from:
# service_single depending on delivered_many_nodeps
# service_unknown depending on delivered_many_nodeps
self.assert_(len(ds) == 2, "Expected 2 dependencies, got %s" %
len(ds))
for d in ds:
actual = d.manifest.replace(self.proto_dir + "/", "")
expected = self.paths["delivered_many_nodeps"]
self.assertEqual(actual, expected,
"Expected dependency path %s, got %s" %
(actual, expected))
self.check_smf_fmris(pkg_attrs,
self.smf_fmris["service_single"] +
self.smf_fmris["delivered_many_nodeps"] +
self.smf_fmris["service_unknown"],
"faildeps_smf_manf")
if __name__ == "__main__":
unittest.main()