Skip to main content

Source code file content

Revision: 31

16764165 overlay files may be removed unexpectedly during pkg operations 16765529 preserve semantics ignored for overlay file updates
» Project Revision History

» Checkout URL

website-repo / webrev / srwalker / pkg-overlay-1 / src / tests / cli / t_pkg_install.py-.html

Size: 387116 bytes, 1 line
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><meta http-equiv="cache-control" content="no-cache"></meta>
<meta http-equiv="Pragma" content="no-cache"></meta>
<meta http-equiv="Expires" content="-1"></meta>
<!--
   Note to customizers: the body of the webrev is IDed as SUNWwebrev
   to allow easy overriding by users of webrev via the userContent.css
   mechanism available in some browsers.

   For example, to have all "removed" information be red instead of
   brown, set a rule in your userContent.css file like:

       body#SUNWwebrev span.removed { color: red ! important; }
-->
<style type="text/css" media="screen">
body {
    background-color: #eeeeee;
}
hr {
    border: none 0;
    border-top: 1px solid #aaa;
    height: 1px;
}
div.summary {
    font-size: .8em;
    border-bottom: 1px solid #aaa;
    padding-left: 1em;
    padding-right: 1em;
}
div.summary h2 {
    margin-bottom: 0.3em;
}
div.summary table th {
    text-align: right;
    vertical-align: top;
    white-space: nowrap;
}
span.lineschanged {
    font-size: 0.7em;
}
span.oldmarker {
    color: red;
    font-size: large;
    font-weight: bold;
}
span.newmarker {
    color: green;
    font-size: large;
    font-weight: bold;
}
span.removed {
    color: brown;
}
span.changed {
    color: blue;
}
span.new {
    color: blue;
    font-weight: bold;
}
span.chmod {
    font-size: 0.7em;
    color: #db7800;
}
a.print { font-size: x-small; }
a:hover { background-color: #ffcc99; }
</style>

<style type="text/css" media="print">
pre { font-size: 0.8em; font-family: courier, monospace; }
span.removed { color: #444; font-style: italic }
span.changed { font-weight: bold; }
span.new { font-weight: bold; }
span.newmarker { font-size: 1.2em; font-weight: bold; }
span.oldmarker { font-size: 1.2em; font-weight: bold; }
a.print {display: none}
hr { border: none 0; border-top: 1px solid #aaa; height: 1px; }
</style>

<title>pkg-gate Old src/tests/cli/t_pkg_install.py</title>
<body id="SUNWwebrev">
<pre>
   1 #!/usr/bin/python
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 
  23 #
  24 # Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
  25 #
  26 
  27 import testutils
  28 if __name__ == "__main__":
  29         testutils.setup_environment("../../../proto")
  30 import pkg5unittest
  31 
  32 import errno
  33 import os
  34 import platform
  35 import re
  36 import shutil
  37 import socket
  38 import stat
  39 import time
  40 import unittest
  41 import urllib2
  42 
  43 import pkg.actions
  44 import pkg.fmri as fmri
  45 import pkg.manifest as manifest
  46 import pkg.portable as portable
  47 
  48 from pkg.client.pkgdefs import EXIT_OOPS
  49 
  50 class TestPkgInstallBasics(pkg5unittest.SingleDepotTestCase):
  51         # Only start/stop the depot once (instead of for every test)
  52         persistent_setup = True
  53 
  54         foo10 = """
  55             open foo@1.0,5.11-0
  56             close """
  57 
  58         foo11 = """
  59             open foo@1.1,5.11-0
  60             add dir mode=0755 owner=root group=bin path=/lib
  61             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1 timestamp="20080731T024051Z"
  62             close """
  63         foo11_timestamp = 1217472051
  64 
  65         foo12 = """
  66             open foo@1.2,5.11-0
  67             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1
  68             close """
  69 
  70         afoo10 = """
  71             open a/foo@1.0,5.11-0
  72             close """
  73 
  74         boring10 = """
  75             open boring@1.0,5.11-0
  76             close """
  77 
  78         boring11 = """
  79             open boring@1.1,5.11-0
  80             close """
  81 
  82         bar10 = """
  83             open bar@1.0,5.11-0
  84             add depend type=require fmri=pkg:/foo@1.0
  85             add dir mode=0755 owner=root group=bin path=/bin
  86             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
  87             close """
  88 
  89         bar11 = """
  90             open bar@1.1,5.11-0
  91             add depend type=require fmri=pkg:/foo@1.2
  92             add dir mode=0755 owner=root group=bin path=/bin
  93             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
  94             close """
  95 
  96         xfoo10 = """
  97             open xfoo@1.0,5.11-0
  98             close """
  99 
 100         xbar10 = """
 101             open xbar@1.0,5.11-0
 102             add depend type=require fmri=pkg:/xfoo@1.0
 103             add dir mode=0755 owner=root group=bin path=/bin
 104             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 105             close """
 106 
 107         xbar11 = """
 108             open xbar@1.1,5.11-0
 109             add depend type=require fmri=pkg:/xfoo@1.2
 110             add dir mode=0755 owner=root group=bin path=/bin
 111             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 112             close """
 113 
 114 
 115         bar12 = """
 116             open bar@1.2,5.11-0
 117             add depend type=require fmri=pkg:/foo@1.0
 118             add dir mode=0755 owner=root group=bin path=/bin
 119             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 120             close """
 121 
 122         baz10 = """
 123             open baz@1.0,5.11-0
 124             add depend type=require fmri=pkg:/foo@1.0
 125             add dir mode=0755 owner=root group=bin path=/bin
 126             add file tmp/baz mode=0555 owner=root group=bin path=/bin/baz
 127             close """
 128 
 129         deep10 = """
 130             open deep@1.0,5.11-0
 131             add depend type=require fmri=pkg:/bar@1.0
 132             add dir mode=0755 owner=root group=bin path=/bin
 133             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 134             close """
 135 
 136         xdeep10 = """
 137             open xdeep@1.0,5.11-0
 138             add depend type=require fmri=pkg:/xbar@1.0
 139             add dir mode=0755 owner=root group=bin path=/bin
 140             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 141             close """
 142 
 143         ydeep10 = """
 144             open ydeep@1.0,5.11-0
 145             add depend type=require fmri=pkg:/ybar@1.0
 146             add dir mode=0755 owner=root group=bin path=/bin
 147             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 148             close """
 149 
 150         a6018_1 = """
 151             open a6018@1.0,5.11-0
 152             close """
 153 
 154         a6018_2 = """
 155             open a6018@2.0,5.11-0
 156             close """
 157 
 158         b6018_1 = """
 159             open b6018@1.0,5.11-0
 160             add depend type=optional fmri=a6018@1
 161             close """
 162 
 163         badfile10 = """
 164             open badfile@1.0,5.11-0
 165             add file tmp/baz mode=644 owner=root group=bin path=/tmp/baz-file
 166             close """
 167 
 168         baddir10 = """
 169             open baddir@1.0,5.11-0
 170             add dir mode=755 owner=root group=bin path=/tmp/baz-dir
 171             close """
 172 
 173         a16189 = """
 174             open a16189@1.0,5.11-0
 175             add depend type=require fmri=pkg:/b16189@1.0
 176             close """
 177 
 178         b16189 = """
 179             open b16189@1.0,5.11-0
 180             add dir mode=0755 owner=root group=bin path=/bin
 181             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
 182             close """
 183 
 184         fuzzy = """
 185             open fuzzy@1.0,5.11-0
 186             add dir mode=0755 owner=root group=bin path="opt/dir with white\tspace"
 187             add file tmp/cat mode=0644 owner=root group=bin path="opt/dir with white\tspace/cat in a hat"
 188             close
 189             open fuzzy@2.0,5.11-0
 190             add dir mode=0755 owner=root group=bin path="opt/dir with white\tspace"
 191             add file tmp/cat mode=0644 owner=root group=bin path="opt/dir with white\tspace/cat in a hat"
 192             add link path=etc/cat_link target="../opt/dir with white\tspace/cat in a hat"
 193             close """
 194 
 195         misc_files = [ "tmp/libc.so.1", "tmp/cat", "tmp/baz" ]
 196 
 197         def setUp(self):
 198                 pkg5unittest.SingleDepotTestCase.setUp(self)
 199                 self.make_misc_files(self.misc_files)
 200 
 201         def test_cli(self):
 202                 """Test bad cli options"""
 203 
 204                 self.image_create(self.rurl)
 205 
 206                 self.pkg("-@", exit=2)
 207                 self.pkg("-s status", exit=2)
 208                 self.pkg("-R status", exit=2)
 209 
 210                 self.pkg("install -@ foo", exit=2)
 211                 self.pkg("install -vq foo", exit=2)
 212                 self.pkg("install", exit=2)
 213                 self.pkg("install foo@x.y", exit=1)
 214                 self.pkg("install pkg:/foo@bar.baz", exit=1)
 215 
 216         def test_basics_1(self):
 217                 """ Send empty package foo@1.0, install and uninstall """
 218 
 219                 plist = self.pkgsend_bulk(self.rurl, self.foo10)
 220                 self.image_create(self.rurl)
 221 
 222                 self.pkg("list -a")
 223                 self.pkg("list", exit=1)
 224 
 225                 self.pkg("install --parsable=0 foo")
 226                 self.assertEqualParsable(self.output,
 227                     add_packages=plist)
 228 
 229                 self.pkg("list")
 230                 self.pkg("verify")
 231 
 232                 self.pkg("uninstall --parsable=0 foo")
 233                 self.assertEqualParsable(self.output,
 234                     remove_packages=plist)
 235                 self.pkg("verify")
 236 
 237         def test_basics_2(self):
 238                 """ Send package foo@1.1, containing a directory and a file,
 239                     install, search, and uninstall. """
 240 
 241                 # This test needs to use the depot to be able to test the
 242                 # download cache.
 243                 self.dc.start()
 244 
 245                 self.pkgsend_bulk(self.durl, (self.foo10, self.foo11),
 246                     refresh_index=True)
 247                 self.image_create(self.durl)
 248 
 249                 self.pkg("list -a")
 250                 self.pkg("install foo")
 251 
 252                 # Verify that content cache is empty after successful install.
 253                 api_inst = self.get_img_api_obj()
 254                 img_inst = api_inst.img
 255                 cache_dirs = []
 256                 for path, readonly, pub, layout in img_inst.get_cachedirs():
 257                         if os.path.exists(path):
 258                                 cache_dirs.extend(os.listdir(path))
 259                 self.assertEqual(cache_dirs, [])
 260 
 261                 self.pkg("verify")
 262                 self.pkg("list")
 263 
 264                 self.pkg("search -l /lib/libc.so.1")
 265                 self.pkg("search -r /lib/libc.so.1")
 266                 self.pkg("search -l blah", exit=1)
 267                 self.pkg("search -r blah", exit=1)
 268 
 269                 # check to make sure timestamp was set to correct value
 270                 libc_path = os.path.join(self.get_img_path(), "lib/libc.so.1")
 271                 lstat = os.stat(libc_path)
 272 
 273                 assert (lstat[stat.ST_MTIME] == self.foo11_timestamp)
 274 
 275                 # check that verify finds changes
 276                 now = time.time()
 277                 os.utime(libc_path, (now, now))
 278                 self.pkg("verify", exit=1)
 279 
 280                 self.pkg("uninstall foo")
 281                 self.pkg("verify")
 282                 self.pkg("list -a")
 283                 self.pkg("verify")
 284                 self.dc.stop()
 285 
 286         def test_basics_3(self):
 287                 """ Install foo@1.0, upgrade to foo@1.1, uninstall. """
 288 
 289                 # This test needs to use the depot to be able to test the
 290                 # download cache.
 291                 self.dc.start()
 292 
 293                 self.pkgsend_bulk(self.durl, (self.foo10, self.foo11))
 294                 self.image_create(self.durl)
 295                 self.pkg("set-property flush-content-cache-on-success False")
 296 
 297                 # Verify that content cache is empty before install.
 298                 api_inst = self.get_img_api_obj()
 299                 img_inst = api_inst.img
 300                 cache_dirs = []
 301                 for path, readonly, pub, layout in img_inst.get_cachedirs():
 302                         if os.path.exists(path):
 303                                 cache_dirs.extend(os.listdir(path))
 304                 self.assertEqual(cache_dirs, [])
 305 
 306                 self.pkg("install foo@1.0")
 307                 self.pkg("list foo@1.0")
 308                 self.pkg("list foo@1.1", exit=1)
 309 
 310                 self.pkg("install foo@1.1")
 311 
 312                 # Verify that content cache is not empty after successful
 313                 # install (since flush-content-cache-on-success is True
 314                 # by default) for packages that have content.
 315                 cache_dirs = []
 316                 for path, readonly, pub, layout in img_inst.get_cachedirs():
 317                         if os.path.exists(path):
 318                                 cache_dirs.extend(os.listdir(path))
 319                 self.assertNotEqual(cache_dirs, [])
 320 
 321                 self.pkg("list foo@1.1")
 322                 self.pkg("list foo@1.0", exit=1)
 323                 self.pkg("list foo@1")
 324                 self.pkg("verify")
 325 
 326                 self.pkg("uninstall foo")
 327                 self.pkg("list -a")
 328                 self.pkg("verify")
 329                 self.dc.stop()
 330 
 331         def test_basics_4(self):
 332                 """ Add bar@1.0, dependent on foo@1.0, install, uninstall. """
 333 
 334                 # This test needs to use the depot to be able to test the
 335                 # download cache.
 336                 self.dc.start()
 337 
 338                 self.pkgsend_bulk(self.durl, (self.foo10, self.foo11,
 339                     self.bar10))
 340                 self.image_create(self.durl)
 341 
 342                 # Set content cache to not be flushed on success.
 343                 self.pkg("set-property flush-content-cache-on-success False")
 344 
 345                 # Verify that content cache is empty before install.
 346                 api_inst = self.get_img_api_obj()
 347                 img_inst = api_inst.img
 348                 cache_dirs = []
 349                 for path, readonly, pub, layout in img_inst.get_cachedirs():
 350                         if os.path.exists(path):
 351                                 cache_dirs.extend(os.listdir(path))
 352                 self.assertEqual(cache_dirs, [])
 353 
 354                 self.pkg("list -a")
 355                 self.pkg("install bar@1.0")
 356 
 357                 # Verify that content cache is not empty after successful
 358                 # install (since flush-content-cache-on-success is False)
 359                 # for packages that have content.
 360                 cache_dirs = []
 361                 for path, readonly, pub, layout in img_inst.get_cachedirs():
 362                         if os.path.exists(path):
 363                                 cache_dirs.extend(os.listdir(path))
 364                 self.assertNotEqual(cache_dirs, [])
 365 
 366                 self.pkg("list")
 367                 self.pkg("verify")
 368                 self.pkg("uninstall -v bar foo")
 369 
 370                 # foo and bar should not be installed at this point
 371                 self.pkg("list bar", exit=1)
 372                 self.pkg("list foo", exit=1)
 373                 self.pkg("verify")
 374                 self.dc.stop()
 375 
 376         def test_basics_5(self):
 377                 """ Install bar@1.0, upgrade to bar@1.1.
 378                 Boring should be left alone, while
 379                 foo gets upgraded as needed"""
 380 
 381                 self.pkgsend_bulk(self.rurl, (self.bar10, self.bar11,
 382                     self.foo10, self.foo11, self.foo12, self.boring10,
 383                     self.boring11))
 384                 self.image_create(self.rurl)
 385 
 386                 self.pkg("install foo@1.0 bar@1.0 boring@1.0")
 387                 self.pkg("list")
 388                 self.pkg("list foo@1.0 boring@1.0 bar@1.0")
 389                 self.pkg("install -v bar@1.1") # upgrade bar
 390                 self.pkg("list")
 391                 self.pkg("list bar@1.1 foo@1.2 boring@1.0")
 392 
 393         def test_basics_6(self):
 394                 """Verify that '@latest' will install the latest version
 395                 of a package."""
 396 
 397                 # Create a repository for the test publisher.
 398                 t1dir = os.path.join(self.test_root, "test-repo")
 399                 self.create_repo(t1dir, properties={ "publisher": {
 400                     "prefix": "test" } })
 401                 self.pkgsend_bulk(t1dir, (self.bar10,
 402                     self.foo10, self.foo11, self.foo12, self.boring10,
 403                     self.boring11))
 404                 self.image_create("file:%s" % t1dir)
 405 
 406                 # Create a repository for a different publisher for at
 407                 # least one of the packages so that we can verify that
 408                 # publisher search order is accounted for by @latest.
 409                 # The second publisher is called 'pub2' here so that
 410                 # it comes lexically before 'test' (see bug 18180) to
 411                 # ensure that latest version ordering works correctly
 412                 # when the same stem is provided by different publishers.
 413                 t2dir = os.path.join(self.test_root, "pub2-repo")
 414                 self.create_repo(t2dir, properties={ "publisher": {
 415                     "prefix": "pub2" } })
 416                 self.pkgsend_bulk(t2dir, self.bar11)
 417 
 418                 self.pkg("set-publisher -p %s" % t2dir)
 419                 self.pkg("install '*@latest'")
 420 
 421                 # 1.0 of bar should be installed here since pub2 is a
 422                 # lower-ranked publisher.
 423                 self.pkg("list")
 424                 self.pkg("info bar@1.0 foo@1.2 boring@1.1")
 425 
 426                 self.pkg("set-publisher --non-sticky test")
 427                 self.pkg("set-publisher -P pub2 ")
 428                 self.pkg("install bar@latest")
 429 
 430                 # 1.1 of bar should be installed here since pub2 is a
 431                 # higher-ranked publisher and test is non-sticky.
 432                 self.pkg("list")
 433                 self.pkg("info bar@1.1")
 434 
 435                 # Cleanup.
 436                 shutil.rmtree(t1dir)
 437                 shutil.rmtree(t2dir)
 438 
 439         def test_basics_7(self):
 440                 """ Add bar@1.1, install bar@1.0. """
 441 
 442                 self.pkgsend_bulk(self.rurl, self.xbar11)
 443                 self.image_create(self.rurl)
 444                 self.pkg("install xbar@1.0", exit=1)
 445 
 446         def test_basics_mdns(self):
 447                 """ Send empty package foo@1.0, install and uninstall """
 448 
 449                 self.pkgsend_bulk(self.rurl, self.foo11)
 450                 self.image_create(self.rurl)
 451 
 452                 self.pkg("set-property mirror-discovery True")
 453                 self.pkg("list -a")
 454                 self.pkg("list", exit=1)
 455 
 456                 self.pkg("install foo")
 457 
 458                 self.pkg("list")
 459                 self.pkg("verify")
 460 
 461                 self.pkg("uninstall foo")
 462                 self.pkg("verify")
 463 
 464         def test_basics_ipv6(self):
 465                 """Verify package operations can be performed using a depot
 466                 server being addressed via IPv6."""
 467 
 468                 # This test needs to use the depot to be able to test
 469                 # IPv6 connectivity.
 470                 self.dc.set_address("::1")
 471                 self.dc.start()
 472 
 473                 durl = self.dc.get_depot_url()
 474                 self.pkgsend_bulk(durl, (self.foo10, self.foo12))
 475                 self.wait_repo(self.dc.get_repodir())
 476                 self.image_create(durl)
 477 
 478                 self.pkg("install foo@1.0")
 479                 self.pkg("info foo@1.0")
 480 
 481                 self.pkg("update")
 482                 self.pkg("list")
 483                 self.pkg("info foo@1.2")
 484                 self.pkg("uninstall '*'")
 485                 self.dc.stop()
 486                 self.dc.set_address(None)
 487 
 488         def test_image_upgrade(self):
 489                 """ Send package bar@1.1, dependent on foo@1.2.  Install
 490                     bar@1.0.  List all packages.  Upgrade image. """
 491 
 492                 self.pkgsend_bulk(self.rurl, (self.foo10, self.foo11,
 493                     self.bar10))
 494                 self.image_create(self.rurl)
 495 
 496                 self.pkg("install bar@1.0")
 497 
 498                 self.pkgsend_bulk(self.rurl, (self.foo12, self.bar11))
 499                 self.pkg("refresh")
 500 
 501                 self.pkg("contents -H")
 502                 self.pkg("list")
 503                 self.pkg("refresh")
 504 
 505                 self.pkg("list")
 506                 self.pkg("verify")
 507                 self.pkg("update -v")
 508                 self.pkg("verify")
 509 
 510                 self.pkg("list foo@1.2")
 511                 self.pkg("list bar@1.1")
 512 
 513                 self.pkg("uninstall bar foo")
 514                 self.pkg("verify")
 515 
 516         def test_dependent_uninstall(self):
 517                 """Trying to remove a package that's a dependency of another
 518                 package should fail since uninstall isn't recursive."""
 519 
 520                 self.pkgsend_bulk(self.rurl, (self.foo10, self.bar10))
 521                 self.image_create(self.rurl)
 522 
 523                 self.pkg("install bar@1.0")
 524 
 525                 self.pkg("uninstall -v foo", exit=1)
 526                 self.pkg("list bar")
 527                 self.pkg("list foo")
 528 
 529         def test_bug_1338(self):
 530                 """ Add bar@1.1, dependent on foo@1.2, install bar@1.1. """
 531 
 532                 self.pkg("list -a")
 533                 self.pkgsend_bulk(self.rurl, self.bar11)
 534                 self.image_create(self.rurl)
 535 
 536                 self.pkg("install xbar@1.1", exit=1)
 537 
 538         def test_bug_1338_2(self):
 539                 """ Add bar@1.1, dependent on foo@1.2, and baz@1.0, dependent
 540                     on foo@1.0, install baz@1.0 and bar@1.1. """
 541 
 542                 self.pkgsend_bulk(self.rurl, (self.bar11, self.baz10))
 543                 self.image_create(self.rurl)
 544                 self.pkg("list -a")
 545                 self.pkg("install baz@1.0 bar@1.1")
 546 
 547         def test_bug_1338_3(self):
 548                 """ Add xdeep@1.0, xbar@1.0. xDeep@1.0 depends on xbar@1.0 which
 549                     depends on xfoo@1.0, install xdeep@1.0. """
 550 
 551                 self.pkgsend_bulk(self.rurl, (self.xbar10, self.xdeep10))
 552                 self.image_create(self.rurl)
 553 
 554                 self.pkg("install xdeep@1.0", exit=1)
 555 
 556         def test_bug_1338_4(self):
 557                 """ Add ydeep@1.0. yDeep@1.0 depends on ybar@1.0 which depends
 558                 on xfoo@1.0, install ydeep@1.0. """
 559 
 560                 self.pkgsend_bulk(self.rurl, self.ydeep10)
 561                 self.image_create(self.rurl)
 562 
 563                 self.pkg("install ydeep@1.0", exit=1)
 564 
 565         def test_bug_2795(self):
 566                 """ Try to install two versions of the same package """
 567 
 568                 self.pkgsend_bulk(self.rurl, (self.foo11, self.foo12))
 569                 self.image_create(self.rurl)
 570 
 571                 self.pkg("install foo@1.1 foo@1.2", exit=1)
 572 
 573         def test_bug_6018(self):
 574                 """  From original comment in bug report:
 575 
 576                 Consider a repository that contains:
 577 
 578                 a@1 and a@2
 579 
 580                 b@1 that contains an optional dependency on package a@1
 581 
 582                 If a@1 and b@1 are installed in an image, the "pkg update" command
 583                 produces the following output:
 584 
 585                 $ pkg update
 586                 No updates available for this image.
 587 
 588                 However, "pkg install a@2" works.
 589                 """
 590 
 591                 plist = self.pkgsend_bulk(self.rurl, (self.a6018_1,
 592                     self.a6018_2, self.b6018_1))
 593                 self.image_create(self.rurl)
 594                 self.pkg("install b6018@1 a6018@1")
 595                 # Test the parsable output of update.
 596                 self.pkg("update --parsable=0")
 597                 self.assertEqualParsable(self.output,
 598                     change_packages=[[plist[0], plist[1]]])
 599                 self.pkg("list b6018@1 a6018@2")
 600 
 601         def test_install_matching(self):
 602                 """ Try to [un]install packages matching a pattern """
 603 
 604                 self.pkgsend_bulk(self.rurl, (self.foo10, self.bar10,
 605                     self.baz10))
 606                 self.image_create(self.rurl)
 607                 # don't specify versions here; we have many
 608                 # different versions of foo, bar &amp; baz in repo
 609                 # when entire class is run w/ one repo instance.
 610 
 611                 # first case should fail since multiple patterns
 612                 # match the same pacakge
 613                 self.pkg("install 'ba*' 'b*'", exit=1)
 614                 self.pkg("install 'ba*'", exit=0)
 615                 self.pkg("list foo", exit=0)
 616                 self.pkg("list bar", exit=0)
 617                 self.pkg("list baz", exit=0)
 618                 self.pkg("uninstall 'b*' 'f*'")
 619 
 620                 # However, multiple forms of the same pattern should simply be
 621                 # coalesced and allowed.
 622                 self.pkg("install pkg:/foo /foo ///foo pkg:///foo")
 623                 self.pkg("list")
 624                 self.pkg("verify pkg:/foo /foo ///foo pkg:///foo")
 625                 self.pkg("uninstall pkg:/foo /foo ///foo "
 626                     "pkg:///foo")
 627 
 628         def test_bad_package_actions(self):
 629                 """Test the install of packages that have actions that are
 630                 invalid."""
 631 
 632                 # First, publish the package that will be corrupted and create
 633                 # an image for testing.
 634                 plist = self.pkgsend_bulk(self.rurl, (self.badfile10,
 635                     self.baddir10))
 636                 self.image_create(self.rurl)
 637 
 638                 # This should succeed and cause the manifest to be cached.
 639                 self.pkg("install %s" % " ".join(plist))
 640 
 641                 # While the manifest is cached, get a copy of its contents.
 642                 for p in plist:
 643                         pfmri = fmri.PkgFmri(p)
 644                         mdata = self.get_img_manifest(pfmri)
 645                         if mdata.find("dir") != -1:
 646                                 src_mode = "mode=755"
 647                         else:
 648                                 src_mode = "mode=644"
 649 
 650                         # Now remove the package so corrupt case can be tested.
 651                         self.pkg("uninstall %s" % pfmri.pkg_name)
 652 
 653                         # Now attempt to corrupt the client's copy of the
 654                         # manifest in various ways to check if the client
 655                         # handles missing mode and invalid mode cases for
 656                         # file and directory actions.
 657                         for bad_mode in ("", 'mode=""', "mode=???"):
 658                                 self.debug("Testing with bad mode "
 659                                     "'%s'." % bad_mode)
 660                                 bad_mdata = mdata.replace(src_mode, bad_mode)
 661                                 self.write_img_manifest(pfmri, bad_mdata)
 662                                 self.pkg("--debug manifest_validate=Never "
 663                                     "install %s" % pfmri.pkg_name, exit=1)
 664 
 665                         # Now attempt to corrupt the client's copy of the
 666                         # manifest in various ways to check if the client
 667                         # handles missing or invalid owners and groups.
 668                         for bad_owner in ("", 'owner=""', "owner=invaliduser"):
 669                                 self.debug("Testing with bad owner "
 670                                     "'%s'." % bad_owner)
 671 
 672                                 bad_mdata = mdata.replace("owner=root",
 673                                     bad_owner)
 674                                 self.write_img_manifest(pfmri, bad_mdata)
 675                                 self.pkg("--debug manifest_validate=Never "
 676                                     "install %s" % pfmri.pkg_name, exit=1)
 677 
 678                         for bad_group in ("", 'group=""', "group=invalidgroup"):
 679                                 self.debug("Testing with bad group "
 680                                     "'%s'." % bad_group)
 681 
 682                                 bad_mdata = mdata.replace("group=bin",
 683                                     bad_group)
 684                                 self.write_img_manifest(pfmri, bad_mdata)
 685                                 self.pkg("--debug manifest_validate=Never "
 686                                     "install %s" % pfmri.pkg_name, exit=1)
 687 
 688                         # Now attempt to corrupt the client's copy of the
 689                         # manifest such that actions are malformed.
 690                         for bad_act in (
 691                             'set name=description value="" \" my desc \" ""',
 692                             "set name=com.sun.service.escalations value="):
 693                                 self.debug("Testing with bad action "
 694                                     "'%s'." % bad_act)
 695                                 bad_mdata = mdata + "%s\n" % bad_act
 696                                 self.write_img_manifest(pfmri, bad_mdata)
 697                                 self.pkg("--debug manifest_validate=Never "
 698                                     "install %s" % pfmri.pkg_name, exit=1)
 699 
 700         def test_bug_3770(self):
 701                 """ Try to install a package from a publisher with an
 702                 unavailable repository. """
 703 
 704                 self.pkgsend_bulk(self.rurl, self.foo11)
 705                 self.image_create(self.rurl)
 706 
 707                 # Depot hasn't been started, so client can't connect.
 708                 self.pkg("set-publisher --no-refresh -O %s test" % self.durl)
 709                 self.pkg("install foo@1.1", exit=1)
 710 
 711         def test_bug_9929(self):
 712                 """Make sure that we can uninstall a package that already
 713                 has its contents on disk even when the repository isn't
 714                 accessible."""
 715 
 716                 # Depot required for this test since client doesn't cache
 717                 # files from a file repository by default.
 718                 self.dc.start()
 719                 self.pkgsend_bulk(self.durl, self.foo11)
 720                 self.image_create(self.durl)
 721 
 722                 self.pkg("install foo")
 723 
 724                 # Stop depot, so client can't connect.
 725                 self.dc.stop()
 726                 self.pkg("set-publisher --no-refresh -O %s test" % self.durl)
 727                 self.pkg("uninstall foo")
 728 
 729         def test_bug_16189(self):
 730                 """Create a repository with a pair of manifests.  Have
 731                 pkg A depend upon pkg B.  Rename pkg B on the depot-side
 732                 and attempt to install. This should fail, but not traceback.
 733                 Then, modify the manifest on the serverside, ensuring that
 734                 the contents don't match the hash.  Then try the install again.
 735                 This should also fail, but not traceback."""
 736 
 737                 afmri = self.pkgsend_bulk(self.rurl, self.a16189)
 738                 bfmri = self.pkgsend_bulk(self.rurl, self.b16189)
 739                 self.image_create(self.rurl)
 740 
 741                 repo = self.dc.get_repo()
 742 
 743                 bpath = repo.manifest(bfmri[0])
 744                 old_dirname = os.path.basename(os.path.dirname(bpath))
 745                 old_dirpath = os.path.dirname(os.path.dirname(bpath))
 746                 new_dirname = "potato"
 747                 old_path = os.path.join(old_dirpath, old_dirname)
 748                 new_path = os.path.join(old_dirpath, new_dirname)
 749                 os.rename(old_path, new_path)
 750                 self.pkg("install a16189", exit=1)
 751 
 752                 os.rename(new_path, old_path)
 753                 self.image_destroy()
 754                 self.image_create(self.rurl)
 755 
 756                 apath = repo.manifest(afmri[0])
 757                 afobj = open(apath, "w")
 758                 afobj.write("set name=pkg.summary value=\"banana\"\n")
 759                 afobj.close()
 760                 self.pkg("install a16189", exit=1)
 761 
 762         def test_install_fuzz(self):
 763                 """Verify that packages delivering files with whitespace in
 764                 their paths can be installed, updated, and uninstalled."""
 765 
 766                 self.pkgsend_bulk(self.rurl, self.fuzzy)
 767                 self.image_create(self.rurl)
 768 
 769                 self.pkg("install fuzzy@1")
 770                 self.pkg("verify -v")
 771                 self.pkg("update -vvv fuzzy@2")
 772                 self.pkg("verify -v")
 773 
 774                 for name in (
 775                     "opt/dir with white\tspace/cat in a hat",
 776                     "etc/cat_link",
 777                 ):
 778                         self.debug("fname: %s" % name)
 779                         self.assert_(os.path.exists(os.path.join(self.get_img_path(),
 780                             name)))
 781 
 782                 self.pkg("uninstall -vvv fuzzy")
 783 
 784 
 785 class TestPkgInstallApache(pkg5unittest.ApacheDepotTestCase):
 786 
 787         # Only start/stop the depot once (instead of for every test)
 788         persistent_setup = True
 789 
 790         foo11 = """
 791             open foo@1.1,5.11-0
 792             add dir mode=0755 owner=root group=bin path=/lib
 793             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1 timestamp="20080731T024051Z"
 794             close """
 795 
 796         upgrade_np10 = """
 797             open upgrade-np@1.0,5.11-0
 798             close"""
 799 
 800         misc_files = [ "tmp/libc.so.1" ]
 801 
 802         def setUp(self):
 803                 pkg5unittest.ApacheDepotTestCase.setUp(self, ["test1", "test2"],
 804                     start_depots=True)
 805                 self.make_misc_files(self.misc_files)
 806                 self.durl1 = self.dcs[1].get_depot_url()
 807                 self.durl2 = self.dcs[2].get_depot_url()
 808                 self.pkgsend_bulk(self.durl1, self.foo11)
 809                 self.pkgsend_bulk(self.durl2, self.upgrade_np10)
 810 
 811         def test_corrupt_web_cache(self):
 812                 """Make sure the client can detect corrupt content being served
 813                 to it from a corrupt web cache, modifying its requests to
 814                 retrieve correct content."""
 815 
 816                 fmris = self.pkgsend_bulk(self.durl1, (self.foo11,
 817                     self.upgrade_np10))
 818                 # we need to record just the version string of foo in order
 819                 # to properly quote it later.
 820                 foo_version = fmris[0].split("@")[1]
 821                 self.image_create(self.durl1)
 822 
 823                 # we use the system repository as a convenient way to setup
 824                 # a caching proxy
 825                 self.sysrepo("")
 826                 sc_runtime_dir = os.path.join(self.test_root, "sysrepo_runtime")
 827                 sc_conf = os.path.join(sc_runtime_dir, "sysrepo_httpd.conf")
 828                 sc_cache = os.path.join(self.test_root, "sysrepo_cache")
 829 
 830                 # ensure pkg5srv can write cache content
 831                 os.chmod(sc_cache, 0777)
 832 
 833                 sysrepo_port = self.next_free_port
 834                 self.next_free_port += 1
 835                 sc = pkg5unittest.SysrepoController(sc_conf,
 836                     sysrepo_port, sc_runtime_dir, testcase=self)
 837                 self.register_apache_controller("sysrepo", sc)
 838                 sc.start()
 839 
 840                 sysrepo_url = "http://localhost:%s" % sysrepo_port
 841 
 842                 saved_pkg_sysrepo_env = os.environ.get("PKG_SYSREPO_URL")
 843                 os.environ["PKG_SYSREPO_URL"] = sysrepo_url
 844 
 845                 # create an image, installing a package, to warm up the webcache
 846                 self.image_create(props={"use-system-repo": True})
 847                 self.pkg("install foo@1.1")
 848                 self.pkg("uninstall foo")
 849 
 850                 # now recreate the image.  image_create calls image_destroy,
 851                 # thereby cleaning any cached content in the image.
 852                 self.image_create(props={"use-system-repo": True})
 853 
 854                 def corrupt_path(path, value="noodles\n", rename=False):
 855                         """Given a path, corrupt its contents."""
 856                         self.assert_(os.path.exists(path))
 857                         if rename:                                
 858                                 os.rename(path, path + ".not-corrupt")
 859                                 open(path, "wb").write(value)
 860                         else:
 861                                 df = open(path, "wb")
 862                                 df.write(value)
 863                                 df.close()
 864 
 865                 def corrupt_cache(cache_dir):
 866                         """Given an apache cache, corrupt it's contents."""
 867 
 868                         for dirpath, dirname, filenames in os.walk(cache_dir):
 869                                 for name in filenames:
 870                                         if name.endswith(".header"):
 871                                                 data = name.replace(".header",
 872                                                     ".data")
 873                                                 corrupt_path(os.path.join(
 874                                                     dirpath, data))
 875                 # corrupt our web cache
 876                 corrupt_cache(sc_cache)
 877 
 878                 urls = [
 879                     # we need to quote the version carefully to use exactly the
 880                     # format pkg(1) uses - two logically identical urls that
 881                     # differ only by the way they're quoted are treated by
 882                     # Apache as separate cacheable resources.
 883                     "%s/test1/manifest/0/foo@%s" % (self.durl1, urllib2.quote(
 884                     foo_version)),
 885                     "%s/test1/file/1/8535c15c49cbe1e7cb1a0bf8ff87e512abed66f8" %
 886                     self.durl1,
 887                 ]
 888 
 889                 proxy_handler = urllib2.ProxyHandler({"http": sysrepo_url})
 890                 proxy_opener = urllib2.build_opener(proxy_handler)
 891 
 892                 # validate that our cache is returning corrupt urls.
 893                 for url in urls:
 894                         self.debug("url:%s" % url)
 895                         # we should get clean content when we don't use the
 896                         # cache
 897                         u = urllib2.urlopen(url)
 898                         content = u.readlines()
 899                         self.assert_(content != ["noodles\n"],
 900                             "Unexpected content from depot")
 901 
 902                         # get the corrupted version, and verify it is broken
 903                         req = urllib2.Request(url)
 904                         u = proxy_opener.open(req)
 905                         content = u.readlines()
 906 
 907                         self.assert_(content == ["noodles\n"],
 908                             "Expected noodles, got %s for %s" % (content, url))
 909 
 910                 # the following should work, as pkg should retry requests
 911                 # where it has detected corrupt contents with a
 912                 # "Cache-Control: no-cache" header.
 913                 self.pkg("refresh --full")
 914                 self.pkg("contents -rm foo@1.1")
 915                 self.pkg("install foo@1.1")
 916 
 917                 # since the cache has been refreshed, we should see valid
 918                 # contents when going through the proxy now.
 919                 for url in urls:
 920                         req = urllib2.Request(url)
 921                         u = proxy_opener.open(req)
 922                         content = u.readlines()
 923                         self.assert_(content != ["noodles\n"],
 924                             "Unexpected content from depot")
 925 
 926                 # ensure that when we actually corrupt the repository
 927                 # as well as the cache, we do detect the errors properly.
 928                 corrupt_cache(sc_cache)
 929                 repodir = self.dcs[1].get_repodir()
 930 
 931                 prefix = "publisher/test1"
 932                 self.image_create(props={"use-system-repo": True})
 933 
 934                 # When we corrupt the files in the repository, we intentionally
 935                 # corrupt them with different contents than the the cache,
 936                 # allowing us to check the error messages being printed by the
 937                 # transport subsystem.
 938 
 939                 filepath = os.path.join(repodir,
 940                     "%s/file/85/8535c15c49cbe1e7cb1a0bf8ff87e512abed66f8" %
 941                     prefix)
 942                 mfpath = os.path.join(repodir, "%s/pkg/foo/%s" % (prefix,
 943                     urllib2.quote(foo_version)))
 944                 catpath = os.path.join(repodir, "%s/catalog/catalog.base.C" %
 945                     prefix)
 946 
 947                 try:
 948                         # first corrupt the file
 949                         corrupt_path(filepath, value="spaghetti\n", rename=True)
 950                         self.pkg("install foo@1.1", stderr=True, exit=1)
 951                         os.rename(filepath + ".not-corrupt", filepath)
 952 
 953                         # we should be getting two hash errors, one from the
 954                         # cache, one from the repo. The one from the repo should
 955                         # repeat
 956                         self.assert_(
 957                             "1: Invalid contentpath lib/libc.so.1: chash" in
 958                             self.errout)
 959                         self.assert_(
 960                             "2: Invalid contentpath lib/libc.so.1: chash" in
 961                             self.errout)
 962                         self.assert_("(happened 3 times)" in self.errout)
 963 
 964                         # now corrupt the manifest (we have to re-corrupt the
 965                         # cache, since attempting to install foo above would
 966                         # have caused the cache to refetch the valid manifest
 967                         # from the repo) and remove the version of the manifest
 968                         # cached in the image.
 969                         corrupt_cache(sc_cache)
 970                         corrupt_path(mfpath, value="spaghetti\n", rename=True)
 971                         shutil.rmtree(os.path.join(self.img_path(),
 972                             "var/pkg/publisher/test1/pkg"))
 973                         self.pkg("contents -rm foo@1.1", stderr=True, exit=1)
 974                         os.rename(mfpath + ".not-corrupt", mfpath)
 975                 
 976                         # we should get two hash errors, one from the cache, one
 977                         # from the repo - the one from the repo should repeat.
 978                         self.assert_(
 979                             "1: Invalid content: manifest hash failure" in
 980                             self.errout)
 981                         self.assert_("2: Invalid content: manifest hash failure"
 982                             in self.errout)
 983                         self.assert_("(happened 3 times)" in self.errout)
 984 
 985                         # finally, corrupt the catalog. Given we've asked for a
 986                         # full refresh, we retrieve the upstream version only.
 987                         corrupt_path(catpath, value="spaghetti\n", rename=True)
 988                         self.pkg("refresh --full", stderr=True, exit=1)
 989                         self.assert_("catalog.base.C' is invalid." in
 990                             self.errout)
 991                         os.rename(catpath + ".not-corrupt", catpath)
 992 
 993                 finally:
 994                         # make sure we clean up any corrupt repo contents.
 995                         for path in [filepath, mfpath, catpath]:
 996                                 not_corrupt = path + ".not-corrupt"
 997                                 if os.path.exists(not_corrupt):
 998                                         os.rename(not_corrupt, path)
 999 
1000                         if saved_pkg_sysrepo_env:
1001                                 os.environ["PKG_SYSREPO_URL"] = \
1002                                     saved_pkg_sysrepo_env
1003 
1004         def test_granular_proxy(self):
1005                 """Tests that images can use the set-publisher --proxy argument
1006                 to selectively proxy requests."""
1007 
1008                 # we use the system repository as a convenient way to setup
1009                 # a caching proxy.   Since the image doesn't have the property
1010                 # 'use-system-repo=True', the configuration of the sysrepo
1011                 # will remain static.
1012                 self.image_create(self.durl1)
1013                 self.sysrepo("")
1014                 sc_runtime_dir = os.path.join(self.test_root, "sysrepo_runtime")
1015                 sc_conf = os.path.join(sc_runtime_dir, "sysrepo_httpd.conf")
1016                 sc_cache = os.path.join(self.test_root, "sysrepo_cache")
1017 
1018                 # ensure pkg5srv can write cache content
1019                 os.chmod(sc_cache, 0777)
1020 
1021                 sysrepo_port = self.next_free_port
1022                 self.next_free_port += 1
1023                 sc = pkg5unittest.SysrepoController(sc_conf,
1024                     sysrepo_port, sc_runtime_dir, testcase=self)
1025                 self.register_apache_controller("sysrepo", sc)
1026                 sc.start()
1027                 sysrepo_url = "http://localhost:%s" % sysrepo_port
1028 
1029                 self.image_create()
1030                 self.pkg("set-publisher -p %s --proxy %s" % (self.durl1,
1031                     sysrepo_url))
1032                 self.pkg("install foo")
1033                 self.pkg("uninstall foo")
1034 
1035                 sc.stop()
1036                 # with our proxy offline, and with no other origins
1037                 # available, we should be unable to install
1038                 self.pkg("install --no-refresh foo", exit=1)
1039                 sc.start()
1040 
1041                 # we cannot add another origin with the same url
1042                 self.pkg("set-publisher --no-refresh -g %s test1" %
1043                     self.durl1, exit=1)
1044                 # we cannot add another proxied origin with that url
1045                 self.pkg("set-publisher --no-refresh -g %s "
1046                     "--proxy http://noodles test1" % self.durl1,
1047                     exit=1)
1048 
1049                 # Now add a second, unproxied publisher, ensuring we
1050                 # can install packages from there.  Since the proxy
1051                 # isn't configured to proxy that resource, this tests
1052                 # that the proxy for self.durl1 isn't being used.
1053                 self.pkg("set-publisher -g %s test2" % self.durl2)
1054                 self.pkg("install --no-refresh "
1055                     "pkg://test2/upgrade-np@1.0")
1056                 self.pkg("uninstall pkg://test2/upgrade-np@1.0")
1057                 self.pkg("set-publisher -G %s test2" % self.durl2)
1058 
1059                 # check that runtime proxies are being used - we
1060                 # set a bogus proxy, then ensure our $http_proxy value
1061                 # gets used.
1062                 self.pkg("publisher")
1063                 self.pkg("set-publisher -G %s test1" % self.durl1)
1064                 self.pkg("set-publisher --no-refresh -g %s "
1065                     "--proxy http://noodles test1" % self.durl1)
1066                 env = {"http_proxy": sysrepo_url}
1067                 self.pkg("refresh", env_arg=env)
1068                 self.pkg("install foo", env_arg=env)
1069                 self.pkg("uninstall foo", env_arg=env)
1070 
1071                 # check that $all_proxy works
1072                 env = {"all_proxy": sysrepo_url}
1073                 self.pkg("install foo", env_arg=env)
1074                 self.pkg("uninstall foo", env_arg=env)
1075 
1076                 # now check that no_proxy works
1077                 env["no_proxy"] = "*"
1078                 self.pkg("install foo", env_arg=env)
1079                 self.pkg("refresh --full", env_arg=env)
1080 
1081 
1082 class TestPkgInstallRepoPerTest(pkg5unittest.SingleDepotTestCase):
1083         persistent_setup = False
1084         # Tests in this suite use the read only data directory.
1085         need_ro_data = True
1086 
1087         foo10 = """
1088             open foo@1.0,5.11-0
1089             close """
1090 
1091         disappear10 = """
1092             open disappear@1.0,5.11-0
1093             add file tmp/cat mode=0555 owner=root group=bin path=/bin/cat
1094             close """
1095 
1096         disappear11 = """
1097             open disappear@1.1,5.11-0
1098             close """
1099 
1100         misc_files = ["tmp/cat"]
1101 
1102         def setUp(self):
1103                 pkg5unittest.SingleDepotTestCase.setUp(self)
1104                 self.make_misc_files(self.misc_files)
1105 
1106         def test_install_changed_manifest(self):
1107                 """Test that if a manifest that is being installed is cached
1108                 locally has been changed on the repo is updated, the new
1109                 manifest is used."""
1110 
1111                 plist = self.pkgsend_bulk(self.rurl, self.foo10)
1112 
1113                 self.image_create(self.rurl)
1114                 self.seed_ta_dir("ta3")
1115                 api_inst = self.get_img_api_obj()
1116 
1117                 # Use pkg contents to cache the manifest.
1118                 self.pkg("contents -r foo")
1119 
1120                 # Specify location as filesystem path.
1121                 self.pkgsign_simple(self.dc.get_repodir(), plist[0])
1122 
1123                 # Ensure that the image requires signed manifests.
1124                 self.pkg("set-property signature-policy require-signatures")
1125                 api_inst.reset()
1126 
1127                 # Install the package
1128                 self._api_install(api_inst, ["foo"])
1129 
1130         def test_keep_installed_changed_manifest(self):
1131                 """Test that if a manifest that has been installed is changed on
1132                 the server is updated, the installed manifest is not changed."""
1133 
1134                 pfmri = self.pkgsend_bulk(self.rurl, self.disappear10)[0]
1135 
1136                 self.image_create(self.rurl)
1137                 api_inst = self.get_img_api_obj()
1138 
1139                 # Install the package
1140                 self._api_install(api_inst, ["disappear"])
1141 
1142                 self.assert_(os.path.isfile(os.path.join(
1143                     self.img_path(), "bin", "cat")))
1144                 repo = self.dc.get_repo()
1145                 m_path = repo.manifest(pfmri)
1146                 with open(m_path, "rb") as fh:
1147                         fmri_lines = fh.readlines()
1148                 with open(m_path, "wb") as fh:
1149                         for l in fmri_lines:
1150                                 if "usr/bin/cat" in l:
1151                                         continue
1152                                 fh.write(l)
1153                 repo.rebuild()
1154 
1155                 pfmri = self.pkgsend_bulk(self.rurl, self.disappear11)[0]
1156                 self._api_update(api_inst)
1157                 self.assert_(not os.path.isfile(os.path.join(
1158                     self.img_path(), "bin", "cat")))
1159 
1160 
1161 class TestPkgInstallUpdateReject(pkg5unittest.SingleDepotTestCase):
1162         """Test --reject option to pkg update/install"""
1163         persistent_setup = True
1164 
1165         pkgs = (
1166                 """
1167                     open A@1.0,5.11-0
1168                     add depend type=require-any fmri=pkg:/B@1.0 fmri=pkg:/C@1.0
1169                     close """,
1170                 """
1171                     open A@2.0,5.11-0
1172                     add depend type=require-any fmri=pkg:/B@1.0 fmri=pkg:/C@1.0
1173                     close """,
1174 
1175                 """
1176                     open B@1.0,5.11-0
1177                     add depend type=exclude fmri=pkg:/C
1178                     close """,
1179 
1180                 """
1181                     open C@1.0,5.11-0
1182                     add depend type=exclude fmri=pkg:/B
1183                     close """,
1184 
1185                 """
1186                     open kernel@1.0,5.11-0.1
1187                     add depend type=require fmri=pkg:/incorp
1188                     close """,
1189 
1190                 """
1191                     open kernel@1.0,5.11-0.2
1192                     add depend type=require fmri=pkg:/incorp
1193                     close """,
1194 
1195                 """
1196                     open incorp@1.0,5.11-0.1
1197                     add depend type=incorporate fmri=kernel@1.0,5.11-0.1
1198                     close """,
1199 
1200                  """
1201                     open incorp@1.0,5.11-0.2
1202                     add depend type=incorporate fmri=kernel@1.0,5.11-0.2
1203                     close """,
1204 
1205                 """
1206                     open kernel@1.0,5.11-0.1.1.0
1207                     add depend type=require fmri=pkg:/incorp
1208                     add depend type=require fmri=pkg:/idr1
1209                     close """,
1210 
1211 
1212                 """
1213                     open kernel@1.0,5.11-0.1.1.1
1214                     add depend type=require fmri=pkg:/incorp
1215                     add depend type=require fmri=pkg:/idr1
1216                     close """,
1217 
1218                 """
1219                     open kernel@1.0,5.11-0.1.2.0
1220                     add depend type=require fmri=pkg:/incorp
1221                     add depend type=require fmri=pkg:/idr2
1222                     close """,
1223 
1224                 """
1225                     open idr1@1.0,5.11-0.1.1.0
1226                     add depend type=incorporate fmri=kernel@1.0,5.11-0.1.1.0
1227                     add depend type=require fmri=idr1_entitlement
1228                     close """,
1229 
1230                 """
1231                     open idr1@1.0,5.11-0.1.1.1
1232                     add depend type=incorporate fmri=kernel@1.0,5.11-0.1.1.1
1233                     add depend type=require fmri=idr1_entitlement
1234                     close """,
1235 
1236                 """
1237                     open idr2@1.0,5.11-0.1.2.0
1238                     add depend type=incorporate fmri=kernel@1.0,5.11-0.1.2.0
1239                     add depend type=require fmri=idr2_entitlement
1240                     close """,
1241 
1242                 """
1243                     open idr1_entitlement@1.0,5.11-0
1244                     add depend type=exclude fmri=no-idrs
1245                     close """,
1246 
1247                 """
1248                     open idr2_entitlement@1.0,5.11-0
1249                     add depend type=exclude fmri=no-idrs
1250                     close """,
1251 
1252                 # hack to prevent idrs from being installed from repo...
1253 
1254                 """
1255                     open no-idrs@1.0,5.11-0
1256                     close """,
1257 
1258                 """
1259                     open pkg://contrib/bogus@1.0,5.11-0
1260                     add depend type=exclude fmri=A
1261                     add depend type=require fmri=bogus1
1262                     add depend type=require fmri=bogus2
1263                     close """,
1264 
1265                 """
1266                     open pkg://contrib/bogus1@1.0,5.11-0
1267                     add depend type=exclude fmri=B
1268                     close """,
1269 
1270                 """
1271                     open pkg://contrib/bogus2@1.0,5.11-0
1272                     add depend type=exclude fmri=C
1273                     close """
1274 
1275                 )
1276 
1277 
1278         def setUp(self):
1279                 pkg5unittest.SingleDepotTestCase.setUp(self)
1280                 self.pkgsend_bulk(self.rurl, self.pkgs)
1281 
1282         def test_install(self):
1283                 self.image_create(self.rurl, prefix="")
1284                 # simple test of reject
1285                 self.pkg("install --reject B A")
1286                 self.pkg("list A C")
1287                 self.pkg("uninstall '*'")
1288                 self.pkg("install --reject C A")
1289                 self.pkg("list A B")
1290                 self.pkg("uninstall '*'")
1291 
1292                 # test swapping XOR'd pkgs B &amp; C w/o uninstalling A
1293                 self.pkg("install B")
1294                 self.pkg("install A")
1295                 self.pkg("list A B")
1296                 self.pkg("install --reject B C")
1297                 self.pkg("list A C")
1298                 self.pkg("uninstall '*'")
1299 
1300                 # test that solver picks up on impossible cases
1301                 self.pkg("install -v --reject B --reject C A", exit=1)
1302 
1303                 # test that publisher matching works
1304                 self.pkg("install bogus")
1305                 self.pkg("list bogus")
1306                 self.pkg("install --reject B --reject 'pkg://contrib/*' A")
1307 
1308                 # verify that matching accounts for reject.
1309                 self.pkg("uninstall '*'")
1310                 self.pkg("install -v --reject A A", exit=1)
1311                 self.pkg("install -v --reject 'idr*' --reject 'bogus*' "
1312                     "--reject B '*'")
1313                 self.pkg("list 'idr*' 'bogus*' B", exit=1)
1314                 self.pkg("list A C incorp kernel no-idrs")
1315 
1316         def test_idr(self):
1317                 self.image_create(self.rurl)
1318                 # install kernel pkg; remember version so we can reinstall it later
1319                 self.pkg("install no-idrs")
1320                 self.pkg("install -v kernel@1.0,5.11-0.1")
1321                 self.pkg("list -Hv kernel@1.0,5.11-0.1 | /usr/bin/awk '{print $1}'")
1322                 kernel_fmri = self.output
1323                 # upgrade to next version w/o encountering idrs
1324                 self.pkg("update -v");
1325                 self.pkg("list kernel@1.0,5.11-0.2")
1326                 self.pkg("list")
1327 
1328                 # try installing idr1; testing wild card support as well
1329                 self.pkg("uninstall no-idrs")
1330                 self.pkg("install --reject 'k*' --reject 'i*'  no-idrs")
1331                 self.pkg("install -v kernel@1.0,5.11-0.1")
1332                 self.pkg("install -v --reject no-idrs idr1_entitlement")
1333                 self.pkg("install -v idr1@1.0,5.11-0.1.1.0")
1334                 self.pkg("update -v --reject idr2")
1335                 self.pkg("list idr1@1.0,5.11-0.1.1.1")
1336 
1337                 # switch to idr2, which affects same package
1338                 self.pkg("install -v --reject idr1 --reject 'idr1_*' idr2 idr2_entitlement")
1339 
1340                 # switch back to base version of kernel
1341                 self.pkg("update -v --reject idr2 --reject 'idr2_*' %s" % kernel_fmri)
1342 
1343                 # reinstall idr1, then update to version 2 of base kernel
1344                 self.pkg("install -v idr1@1.0,5.11-0.1.1.0 idr1_entitlement")
1345                 self.pkg("list kernel@1.0,5.11-0.1.1.0")
1346                 # Wildcards are purposefully used here for both patterns to
1347                 # ensure pattern matching works as expected for update.
1348                 self.pkg("update -v --reject 'idr1*' '*incorp@1.0-0.2'")
1349                 self.pkg("list  kernel@1.0,5.11-0.2")
1350 
1351         def test_update(self):
1352                 self.image_create(self.rurl)
1353                 # Test update reject without wildcards.
1354                 self.pkg("install  kernel@1.0,5.11-0.1.1.0 A@1.0,5.11-0")
1355                 self.pkg("update -v --reject A")
1356                 self.pkg("list A", exit=1)
1357                 self.pkg("verify")
1358 
1359                 # Reinstall kernel package, install A, and test update again using
1360                 # wildcards.
1361                 self.pkg("uninstall '*'")
1362                 self.pkg("install kernel@1.0,5.11-0.1.1.0")
1363                 self.pkg("list kernel@1.0,5.11-0.1.1.0")
1364                 self.pkg("install A@1.0,5.11-0")
1365                 self.pkg("update -v --reject A '*'")
1366                 self.pkg("list A", exit=1)
1367                 self.pkg("list kernel@1.0,5.11-0.1.1.1")
1368                 self.pkg("verify")
1369 
1370 
1371 class TestPkgInstallAmbiguousPatterns(pkg5unittest.SingleDepotTestCase):
1372 
1373         # An "ambiguous" package name pattern is one which, because of the
1374         # pattern matching rules, might refer to more than one package.  This
1375         # may be as obvious as the pattern "SUNW*", but also like the pattern
1376         # "foo", where "foo" and "a/foo" both exist in the catalog.
1377 
1378         afoo10 = """
1379             open a/foo@1.0,5.11-0
1380             close """
1381 
1382         bfoo10 = """
1383             open b/foo@1.0,5.11-0
1384             close """
1385 
1386         bar10 = """
1387             open bar@1.0,5.11-0
1388             close """
1389 
1390         foo10 = """
1391             open foo@1.0,5.11-0
1392             close """
1393 
1394         foo11 = """
1395             open foo@1.1,5.11-0
1396             close """
1397 
1398         anotherfoo11 = """
1399             open another/foo@1.1,5.11-0
1400             close """
1401 
1402         depender10 = """
1403             open depender@1.0,5.11-0
1404             add depend type=require fmri=foo@1.0
1405             close """
1406 
1407         depender11 = """
1408             open depender@1.1,5.11-0
1409             add depend type=require fmri=foo@1.1
1410             close """
1411 
1412         def test_bug_4204(self):
1413                 """Don't stack trace when printing a PlanCreationException with
1414                 "multiple_matches" populated (on uninstall)."""
1415 
1416                 self.pkgsend_bulk(self.rurl, (self.afoo10, self.bfoo10,
1417                     self.bar10))
1418                 self.image_create(self.rurl)
1419 
1420                 self.pkg("install foo", exit=1)
1421                 self.pkg("install a/foo b/foo", exit=0)
1422                 self.pkg("list")
1423                 self.pkg("uninstall foo", exit=1)
1424                 self.pkg("uninstall a/foo b/foo", exit=0)
1425 
1426         def test_bug_6874(self):
1427                 """Don't stack trace when printing a PlanCreationException with
1428                 "multiple_matches" populated (on install and update)."""
1429 
1430                 self.pkgsend_bulk(self.rurl, (self.afoo10, self.bfoo10))
1431                 self.image_create(self.rurl)
1432 
1433                 self.pkg("install foo", exit=1)
1434 
1435         def test_ambiguous_pattern_install(self):
1436                 """An update should never get confused about an existing
1437                 package being part of an ambiguous set of package names."""
1438 
1439                 self.pkgsend_bulk(self.rurl, self.foo10)
1440 
1441                 self.image_create(self.rurl)
1442                 self.pkg("install foo")
1443 
1444                 self.pkgsend_bulk(self.rurl, self.anotherfoo11)
1445                 self.pkg("refresh")
1446                 self.pkg("update -v", exit=4)
1447 
1448         def test_ambiguous_pattern_depend(self):
1449                 """A dependency on a package should pull in an exact name
1450                 match."""
1451 
1452                 self.pkgsend_bulk(self.rurl, (self.depender10, self.foo10))
1453 
1454                 self.image_create(self.rurl)
1455                 self.pkg("install depender")
1456 
1457                 self.pkgsend_bulk(self.rurl, (self.foo11, self.anotherfoo11,
1458                     self.depender11))
1459                 self.pkg("refresh")
1460 
1461                 self.pkg("install depender")
1462 
1463                 # Make sure that we didn't get other/foo from the dependency.
1464                 self.pkg("list another/foo", exit=1)
1465 
1466         def test_non_ambiguous_fragment(self):
1467                 """We should be able to refer to a package by its "basename", if
1468                 that component is unique."""
1469 
1470                 self.pkgsend_bulk(self.rurl, self.anotherfoo11)
1471                 self.image_create(self.rurl)
1472 
1473                 # Right now, this is not exact, but still unambiguous
1474                 self.pkg("install foo")
1475 
1476                 # Create ambiguity
1477                 self.pkgsend_bulk(self.rurl, self.foo11)
1478                 self.pkg("refresh")
1479 
1480                 # This is unambiguous, should succeed
1481                 self.pkg("install pkg:/foo")
1482 
1483                 # This is now ambiguous, should fail
1484                 self.pkg("install foo", exit=1)
1485 
1486 
1487 class TestPkgInstallOverlappingPatterns(pkg5unittest.SingleDepotTestCase):
1488 
1489         a_1 = """
1490             open a@1.0,5.11-0
1491             close """
1492 
1493         pub2_a_1 = """
1494             open pkg://pub2/a@1.0,5.11-0
1495             close """
1496 
1497         a_11 = """
1498             open a@1.1,5.11-0
1499             close """
1500 
1501         a_2 = """
1502             open a@2.0,5.11-0
1503             close """
1504 
1505         pub2_a_2 = """
1506             open pkg://pub2/a@2.0,5.11-0
1507             close """
1508 
1509         a_3 = """
1510             open a@3.0,5.11-0
1511             close """
1512 
1513         aa_1 = """
1514             open aa@1.0,5.11-0
1515             close """
1516 
1517         afoo_1 = """
1518             open a/foo@1.0,5.11-0
1519             close """
1520 
1521         bfoo_1 = """
1522             open b/foo@1.0,5.11-0
1523             close """
1524 
1525         fooa_1 = """
1526             open foo/a@1.0,5.11-0
1527             close """
1528 
1529         foob_1 = """
1530             open foo/b@1.0,5.11-0
1531             close """
1532 
1533         def test_overlapping_one_package_available(self):
1534                 self.pkgsend_bulk(self.rurl, self.a_1)
1535                 api_inst = self.image_create(self.rurl)
1536 
1537                 self._api_install(api_inst, ["a@1", "a@1"], noexecute=True)
1538                 self._api_install(api_inst, ["a@1", "a@1.0"], noexecute=True)
1539                 self._api_install(api_inst, ["a@1", "pkg://test/a@1"],
1540                     noexecute=True)
1541                 self._api_install(api_inst, ["a*@1", "pkg:/*a@1"],
1542                     noexecute=True)
1543                 self._api_install(api_inst, ["a*@1", "a@1"], noexecute=True)
1544                 self._api_install(api_inst, ["a@1", "pkg://test/a*@1"],
1545                     noexecute=True)
1546                 # This fails because a*@2 matches no patterns on its own.
1547                 self.pkg("install -n 'a*@2' 'a@1'", exit=1)
1548 
1549         def test_overlapping_conflicting_versions_no_wildcard_match(self):
1550                 self.pkgsend_bulk(self.rurl, self.a_1 + self.a_2)
1551                 api_inst = self.image_create(self.rurl)
1552 
1553                 self.pkg("install -n a@1 a@2", exit=1)
1554                 self.pkg("install -n a@2 pkg://test/a@1", exit=1)
1555                 self.pkg("install -n 'a*@2' 'pkg:/*a@1'", exit=1)
1556 
1557                 # This is allowed because a*@1 matches published packages, even
1558                 # though the packages it matches aren't installed in the image.
1559                 self._api_install(api_inst, ["a*@1", "a@2"])
1560                 self.pkg("list a@2")
1561                 self._api_uninstall(api_inst, ["a"])
1562 
1563                 self._api_install(api_inst, ["a@1", "pkg://test/a*@2"])
1564                 self.pkg("list a@1")
1565                 self._api_uninstall(api_inst, ["a"])
1566 
1567                 self.pkgsend_bulk(self.rurl, self.a_3)
1568                 self._api_install(api_inst, ["a*@1", "*a@2", "a@3"])
1569                 self.pkg("list a@3")
1570                 self._api_uninstall(api_inst, ["a"])
1571 
1572                 self._api_install(api_inst, ["a*@1", "*a@2", "a@latest"])
1573                 self.pkg("list a@3")
1574                 self._api_uninstall(api_inst, ["a"])
1575 
1576                 self.pkgsend_bulk(self.rurl, self.a_11)
1577                 self.pkg("install a@1.1 a@1.0", exit=1)
1578                 self._api_install(api_inst, ["a@1", "a@1.0", "a*@1.1"])
1579                 self.pkg("list a@1.0")
1580                 self._api_uninstall(api_inst, ["a"])
1581 
1582                 self._api_install(api_inst, ["*", "a@1.0"])
1583                 self.pkg("list a@1.0")
1584                 self._api_uninstall(api_inst, ["a"])
1585 
1586         def test_overlapping_multiple_packages(self):
1587                 self.pkgsend_bulk(self.rurl, self.a_1 + self.a_2 + self.aa_1 +
1588                     self.afoo_1 + self.bfoo_1 + self.fooa_1 + self.foob_1)
1589                 api_inst = self.image_create(self.rurl)
1590 
1591                 self.pkg("install '*a@1' 'a*@2'", exit=1)
1592 
1593                 self._api_install(api_inst, ["a*@1", "a@2"])
1594                 self.pkg("list -Hv")
1595                 self.assertEqual(len(self.output.splitlines()), 3)
1596                 self.assert_("a@2" in self.output)
1597                 self._api_uninstall(api_inst, ["a", "aa", "a/foo"])
1598 
1599                 self._api_install(api_inst, ["/a@1", "a*@2", "*foo*@1"])
1600                 self.pkg("list -Hv")
1601                 self.assertEqual(len(self.output.splitlines()), 5)
1602                 self.assert_("a@1" in self.output)
1603                 self._api_uninstall(api_inst,
1604                     ["/a", "a/foo", "b/foo", "foo/a", "foo/b"])
1605 
1606         def test_overlapping_multiple_publishers(self):
1607                 self.pkgsend_bulk(self.rurl, self.a_1 + self.pub2_a_2)
1608                 api_inst = self.image_create(self.rurl)
1609 
1610                 self._api_install(api_inst, ["a*@1", "pkg://pub2/a@2"],
1611                     noexecute=True)
1612                 self._api_install(api_inst, ["a@1", "pkg://pub2/a*@2"],
1613                     noexecute=True)
1614                 self._api_install(api_inst, ["a@1", "pkg://pub2/*@2"],
1615                     noexecute=True)
1616                 self.pkg("install -n 'pkg://test/a*@1' 'pkg://pub2/*a@2'",
1617                     exit=1)
1618                 self.pkg("install -n 'pkg://test/a@1' 'pkg://pub2/a@2'",
1619                     exit=1)
1620                 self.pkg("install -n 'a@1' 'pkg://pub2/a@2'", exit=1)
1621 
1622                 self.pkgsend_bulk(self.rurl, self.pub2_a_1)
1623                 self._api_install(api_inst, ["a@1", "pkg://pub2/a@1"])
1624                 self.pkg("list -Hv 'pkg://pub2/*'")
1625                 self.assertEqual(len(self.output.splitlines()), 1)
1626                 self.assert_("a@1" in self.output)
1627                 self._api_uninstall(api_inst, ["a"])
1628 
1629                 self._api_install(api_inst, ["a@1", "pkg://test/a@1"])
1630                 self.pkg("list -Hv 'pkg://test/*'")
1631                 self.assertEqual(len(self.output.splitlines()), 1)
1632                 self.assert_("a@1" in self.output)
1633                 self._api_uninstall(api_inst, ["a"])
1634 
1635                 self._api_install(api_inst, ["a*@1", "pkg://pub2/*@2"])
1636                 self.pkg("list -Hv 'pkg://pub2/*'")
1637                 self.assertEqual(len(self.output.splitlines()), 1)
1638                 self.assert_("a@2" in self.output)
1639                 self._api_uninstall(api_inst, ["a"])
1640 
1641                 self._api_install(api_inst,
1642                     ["pkg://test/a@1", "pkg://pub2/*@2"])
1643                 self.pkg("list -Hv 'pkg://test/*'")
1644                 self.assertEqual(len(self.output.splitlines()), 1)
1645                 self.assert_("a@1" in self.output)
1646                 self._api_uninstall(api_inst, ["a"])
1647 
1648                 # This intentionally doesn't use api_install to check for
1649                 # special handling of '*' in client.py.
1650                 self.pkg("install '*' 'pkg://pub2/*@2'")
1651                 self.pkg("list -Hv 'pkg://pub2/*'")
1652                 self.assertEqual(len(self.output.splitlines()), 1)
1653                 self.assert_("a@2" in self.output)
1654                 self._api_uninstall(api_inst, ["a"])
1655 
1656 
1657 class TestPkgInstallCircularDependencies(pkg5unittest.SingleDepotTestCase):
1658         # Only start/stop the depot once (instead of for every test)
1659         persistent_setup = True
1660 
1661         pkg10 = """
1662             open pkg1@1.0,5.11-0
1663             add depend type=require fmri=pkg:/pkg2
1664             close
1665         """
1666 
1667         pkg20 = """
1668             open pkg2@1.0,5.11-0
1669             add depend type=require fmri=pkg:/pkg3
1670             close
1671         """
1672 
1673         pkg30 = """
1674             open pkg3@1.0,5.11-0
1675             add depend type=require fmri=pkg:/pkg1
1676             close
1677         """
1678 
1679 
1680         pkg11 = """
1681             open pkg1@1.1,5.11-0
1682             add depend type=require fmri=pkg:/pkg2@1.1
1683             close
1684         """
1685 
1686         pkg21 = """
1687             open pkg2@1.1,5.11-0
1688             add depend type=require fmri=pkg:/pkg3@1.1
1689             close
1690         """
1691 
1692         pkg31 = """
1693             open pkg3@1.1,5.11-0
1694             add depend type=require fmri=pkg:/pkg1@1.1
1695             close
1696         """
1697 
1698         def test_unanchored_circular_dependencies(self):
1699                 """ check to make sure we can install
1700                 circular dependencies w/o versions
1701                 """
1702 
1703                 # Send 1.0 versions of packages.
1704                 self.pkgsend_bulk(self.rurl, (self.pkg10, self.pkg20,
1705                     self.pkg30))
1706 
1707                 self.image_create(self.rurl)
1708                 self.pkg("install pkg1")
1709                 self.pkg("list")
1710                 self.pkg("verify -v")
1711 
1712         def test_anchored_circular_dependencies(self):
1713                 """ check to make sure we can install
1714                 circular dependencies w/ versions
1715                 """
1716 
1717                 # Send 1.1 versions of packages.
1718                 self.pkgsend_bulk(self.rurl, (self.pkg11, self.pkg21,
1719                     self.pkg31))
1720 
1721                 self.image_create(self.rurl)
1722                 self.pkg("install pkg1")
1723                 self.pkg("list")
1724                 self.pkg("verify -v")
1725 
1726 
1727 class TestPkgInstallUpgrade(pkg5unittest.SingleDepotTestCase):
1728         # Only start/stop the depot once (instead of for every test)
1729         persistent_setup = True
1730 
1731         incorp10 = """
1732             open incorp@1.0,5.11-0
1733             add depend type=incorporate fmri=pkg:/amber@1.0
1734             add depend type=incorporate fmri=pkg:/bronze@1.0
1735             close
1736         """
1737 
1738         incorp20 = """
1739             open incorp@2.0,5.11-0
1740             add depend type=incorporate fmri=pkg:/amber@2.0
1741             add depend type=incorporate fmri=pkg:/bronze@2.0
1742             close
1743         """
1744 
1745         incorp30 = """
1746             open incorp@3.0,5.11-0
1747             add depend type=incorporate fmri=pkg:/amber@2.0
1748             close
1749         """
1750 
1751         incorpA = """
1752             open incorpA@1.0,5.11-0
1753             add depend type=incorporate fmri=pkg:/amber@1.0
1754             add depend type=incorporate fmri=pkg:/bronze@1.0
1755             close
1756         """
1757 
1758         incorpB =  """
1759             open incorpB@1.0,5.11-0
1760             add depend type=incorporate fmri=pkg:/amber@2.0
1761             add depend type=incorporate fmri=pkg:/bronze@2.0
1762             close
1763         """
1764 
1765         iridium10 = """
1766             open iridium@1.0,5.11-0
1767             add depend fmri=pkg:/amber@2.0 type=require
1768             close
1769         """
1770         amber10 = """
1771             open amber@1.0,5.11-0
1772             add dir mode=0755 owner=root group=bin path=/lib
1773             add dir mode=0755 owner=root group=bin path=/etc
1774             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1
1775             add link path=/lib/libc.symlink target=/lib/libc.so.1
1776             add hardlink path=/lib/libc.hardlink target=/lib/libc.so.1
1777             add file tmp/amber1 mode=0444 owner=root group=bin path=/etc/amber1
1778             add file tmp/amber2 mode=0444 owner=root group=bin path=/etc/amber2
1779             add license tmp/copyright1 license=copyright
1780             close
1781         """
1782 
1783         brass10 = """
1784             open brass@1.0,5.11-0
1785             add depend fmri=pkg:/bronze type=require
1786             close
1787         """
1788 
1789         bronze10 = """
1790             open bronze@1.0,5.11-0
1791             add dir mode=0755 owner=root group=bin path=/usr
1792             add dir mode=0755 owner=root group=bin path=/usr/bin
1793             add file tmp/sh mode=0555 owner=root group=bin path=/usr/bin/sh
1794             add link path=/usr/bin/jsh target=./sh
1795             add hardlink path=/lib/libc.bronze target=/lib/libc.so.1
1796             add file tmp/bronze1 mode=0444 owner=root group=bin path=/etc/bronze1
1797             add file tmp/bronze2 mode=0444 owner=root group=bin path=/etc/bronze2
1798             add file tmp/bronzeA1 mode=0444 owner=root group=bin path=/A/B/C/D/E/F/bronzeA1
1799             add depend fmri=pkg:/amber@1.0 type=require
1800             add license tmp/copyright2 license=copyright
1801             close
1802         """
1803 
1804         amber20 = """
1805             open amber@2.0,5.11-0
1806             add dir mode=0755 owner=root group=bin path=/usr
1807             add dir mode=0755 owner=root group=bin path=/usr/bin
1808             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1
1809             add link path=/lib/libc.symlink target=/lib/libc.so.1
1810             add hardlink path=/lib/libc.amber target=/lib/libc.bronze
1811             add hardlink path=/lib/libc.hardlink target=/lib/libc.so.1
1812             add file tmp/amber1 mode=0444 owner=root group=bin path=/etc/amber1
1813             add file tmp/amber2 mode=0444 owner=root group=bin path=/etc/bronze2
1814             add depend fmri=pkg:/bronze@2.0 type=require
1815             add license tmp/copyright2 license=copyright
1816             close
1817         """
1818 
1819         bronze20 = """
1820             open bronze@2.0,5.11-0
1821             add dir mode=0755 owner=root group=bin path=/etc
1822             add dir mode=0755 owner=root group=bin path=/lib
1823             add file tmp/sh mode=0555 owner=root group=bin path=/usr/bin/sh
1824             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.bronze
1825             add link path=/usr/bin/jsh target=./sh
1826             add hardlink path=/lib/libc.bronze2.0.hardlink target=/lib/libc.so.1
1827             add file tmp/bronze1 mode=0444 owner=root group=bin path=/etc/bronze1
1828             add file tmp/bronze2 mode=0444 owner=root group=bin path=/etc/amber2
1829             add license tmp/copyright3 license=copyright
1830             add file tmp/bronzeA2 mode=0444 owner=root group=bin path=/A1/B2/C3/D4/E5/F6/bronzeA2
1831             add depend fmri=pkg:/amber@2.0 type=require
1832             close
1833         """
1834 
1835         bronze30 = """
1836             open bronze@3.0,5.11-0
1837             add dir mode=0755 owner=root group=bin path=/etc
1838             add dir mode=0755 owner=root group=bin path=/lib
1839             add file tmp/sh mode=0555 owner=root group=bin path=/usr/bin/sh
1840             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.bronze
1841             add link path=/usr/bin/jsh target=./sh
1842             add hardlink path=/lib/libc.bronze2.0.hardlink target=/lib/libc.so.1
1843             add file tmp/bronze1 mode=0444 owner=root group=bin path=/etc/bronze1
1844             add file tmp/bronze2 mode=0444 owner=root group=bin path=/etc/amber2
1845             add license tmp/copyright3 license=copyright
1846             add file tmp/bronzeA2 mode=0444 owner=root group=bin path=/A1/B2/C3/D4/E5/F6/bronzeA2
1847             add depend fmri=pkg:/amber@2.0 type=require
1848             close
1849         """
1850 
1851 
1852         gold10 = """
1853             open gold@1.0,5.11-0
1854             add file tmp/gold-passwd1 mode=0644 owner=root group=bin path=etc/passwd preserve=true
1855             add file tmp/gold-group mode=0644 owner=root group=bin path=etc/group preserve=true
1856             add file tmp/gold-shadow mode=0600 owner=root group=bin path=etc/shadow preserve=true
1857             add file tmp/gold-ftpusers mode=0644 owner=root group=bin path=etc/ftpd/ftpusers preserve=true
1858             add file tmp/gold-silly mode=0644 owner=root group=bin path=etc/silly
1859             add file tmp/gold-silly mode=0644 owner=root group=bin path=etc/silly2
1860             close
1861         """
1862 
1863         gold20 = """
1864             open gold@2.0,5.11-0
1865             add file tmp/config2 mode=0644 owner=root group=bin path=etc/config2 original_name="gold:etc/passwd" preserve=true
1866             close
1867         """
1868 
1869         gold30 = """
1870             open gold@3.0,5.11-0
1871             close
1872         """
1873 
1874         golduser10 = """
1875             open golduser@1.0
1876             add user username=Kermit group=adm home-dir=/export/home/Kermit
1877             close
1878         """
1879 
1880         golduser20 = """
1881             open golduser@2.0
1882             close
1883         """
1884 
1885         silver10  = """
1886             open silver@1.0,5.11-0
1887             close
1888         """
1889 
1890         silver20  = """
1891             open silver@2.0,5.11-0
1892             add file tmp/gold-passwd2 mode=0644 owner=root group=bin path=etc/passwd original_name="gold:etc/passwd" preserve=true
1893             add file tmp/gold-group mode=0644 owner=root group=bin path=etc/group original_name="gold:etc/group" preserve=true
1894             add file tmp/gold-shadow mode=0600 owner=root group=bin path=etc/shadow original_name="gold:etc/shadow" preserve=true
1895             add file tmp/gold-ftpusers mode=0644 owner=root group=bin path=etc/ftpd/ftpusers original_name="gold:etc/ftpd/ftpusers" preserve=true
1896             add file tmp/gold-silly mode=0644 owner=root group=bin path=etc/silly
1897             add file tmp/silver-silly mode=0644 owner=root group=bin path=etc/silly2
1898             close
1899         """
1900         silver30  = """
1901             open silver@3.0,5.11-0
1902             add file tmp/config2 mode=0644 owner=root group=bin path=etc/config2 original_name="gold:etc/passwd" preserve=true
1903             close
1904         """
1905 
1906         silveruser = """
1907             open silveruser@1.0
1908             add user username=Kermit group=adm home-dir=/export/home/Kermit
1909             close
1910         """
1911 
1912 
1913         iron10 = """
1914             open iron@1.0,5.11-0
1915             add dir mode=0755 owner=root group=bin path=etc
1916             add file tmp/config1 mode=0644 owner=root group=bin path=etc/foo
1917             add hardlink path=etc/foo.link target=foo
1918             close
1919         """
1920         iron20 = """
1921             open iron@2.0,5.11-0
1922             add dir mode=0755 owner=root group=bin path=etc
1923             add file tmp/config2 mode=0644 owner=root group=bin path=etc/foo
1924             add hardlink path=etc/foo.link target=foo
1925             close
1926         """
1927 
1928         concorp10 = """
1929             open concorp@1.0,5.11-0
1930             add depend type=incorporate fmri=pkg:/amber@2.0
1931             add depend type=incorporate fmri=pkg:/bronze@2.0
1932             close
1933         """
1934 
1935         dricon1 = """
1936             open dricon@1
1937             add dir path=var mode=755 owner=root group=root
1938             add dir path=var/run mode=755 owner=root group=root
1939             add dir mode=0755 owner=root group=root path=system
1940             add dir mode=0755 owner=root group=root path=system/volatile
1941             add dir path=/tmp mode=755 owner=root group=root
1942             add dir path=/etc mode=755 owner=root group=root
1943             add file tmp/dricon_da path=/etc/driver_aliases mode=644 owner=root group=sys preserve=true
1944             add file tmp/dricon_n2m path=/etc/name_to_major mode=644 owner=root group=sys preserve=true
1945             close
1946         """
1947 
1948         dricon2 = """
1949             open dricon@2
1950             add dir path=var mode=755 owner=root group=root
1951             add dir path=var/run mode=755 owner=root group=root
1952             add dir mode=0755 owner=root group=root path=system
1953             add dir mode=0755 owner=root group=root path=system/volatile
1954             add dir path=/tmp mode=755 owner=root group=root
1955             add dir path=/etc mode=755 owner=root group=root
1956             add file tmp/dricon2_da path=/etc/driver_aliases mode=644 owner=root group=sys preserve=true
1957             add file tmp/dricon_n2m path=/etc/name_to_major mode=644 owner=root group=sys preserve=true
1958             add driver name=zigit alias=pci8086,1234
1959             close
1960         """
1961 
1962         dricon3 = """
1963             open dricon@3
1964             add dir path=var mode=755 owner=root group=root
1965             add dir path=var/run mode=755 owner=root group=root
1966             add dir path=/tmp mode=755 owner=root group=root
1967             add dir path=/etc mode=755 owner=root group=root
1968             add file tmp/dricon2_da path=/etc/driver_aliases mode=644 owner=root group=sys preserve=true
1969             add file tmp/dricon_n2m path=/etc/name_to_major mode=644 owner=root group=sys preserve=true
1970             add driver name=zigit alias=pci8086,1234
1971             add driver name=figit alias=pci8086,1234
1972             close
1973         """
1974 
1975         dripol1 = """
1976             open dripol@1
1977             add dir path=var mode=755 owner=root group=root
1978             add dir path=var/run mode=755 owner=root group=root
1979             add dir mode=0755 owner=root group=root path=system
1980             add dir mode=0755 owner=root group=root path=system/volatile
1981             add dir path=/tmp mode=755 owner=root group=root
1982             add dir path=/etc mode=755 owner=root group=root
1983             add dir path=/etc/security mode=755 owner=root group=root
1984             add file tmp/dricon2_da path=/etc/driver_aliases mode=644 owner=root group=sys preserve=true
1985             add file tmp/dricon_n2m path=/etc/name_to_major mode=644 owner=root group=sys preserve=true
1986             add file tmp/dripol1_dp path=/etc/security/device_policy mode=644 owner=root group=sys preserve=true
1987             add driver name=frigit policy="read_priv_set=net_rawaccess write_priv_set=net_rawaccess"
1988             close
1989         """
1990 
1991         dripol2 = """
1992             open dripol@2
1993             add dir path=var mode=755 owner=root group=root
1994             add dir path=var/run mode=755 owner=root group=root
1995             add dir mode=0755 owner=root group=root path=system
1996             add dir mode=0755 owner=root group=root path=system/volatile
1997             add dir path=/tmp mode=755 owner=root group=root
1998             add dir path=/etc mode=755 owner=root group=root
1999             add dir path=/etc/security mode=755 owner=root group=root
2000             add file tmp/dricon2_da path=/etc/driver_aliases mode=644 owner=root group=sys preserve=true
2001             add file tmp/dricon_n2m path=/etc/name_to_major mode=644 owner=root group=sys preserve=true
2002             add file tmp/dripol1_dp path=/etc/security/device_policy mode=644 owner=root group=sys preserve=true
2003             add driver name=frigit
2004             close
2005         """
2006 
2007         liveroot10 = """
2008             open liveroot@1.0
2009             add dir path=/etc mode=755 owner=root group=root
2010             add file tmp/liveroot1 path=/etc/liveroot mode=644 owner=root group=sys reboot-needed=true
2011             close
2012         """
2013         liveroot20 = """
2014             open liveroot@2.0
2015             add dir path=/etc mode=755 owner=root group=root
2016             add file tmp/liveroot2 path=/etc/liveroot mode=644 owner=root group=sys reboot-needed=true
2017             close
2018         """
2019 
2020         renameold1 = """
2021             open renold@1.0
2022             add file tmp/renold1 path=testme mode=0644 owner=root group=root preserve=renameold
2023             close
2024         """
2025 
2026         renameold2 = """
2027             open renold@2.0
2028             add file tmp/renold1 path=testme mode=0640 owner=root group=root preserve=renameold
2029             close
2030         """
2031 
2032         renameold3 = """
2033             open renold@3.0
2034             add file tmp/renold3 path=testme mode=0644 owner=root group=root preserve=renameold
2035             close
2036         """
2037 
2038         renamenew1 = """
2039             open rennew@1.0
2040             add file tmp/rennew1 path=testme mode=0644 owner=root group=root preserve=renamenew
2041             close
2042         """
2043 
2044         renamenew2 = """
2045             open rennew@2.0
2046             add file tmp/rennew1 path=testme mode=0640 owner=root group=root preserve=renamenew
2047             close
2048         """
2049 
2050         renamenew3 = """
2051             open rennew@3.0
2052             add file tmp/rennew3 path=testme mode=0644 owner=root group=root preserve=renamenew
2053             close
2054         """
2055 
2056         preserve1 = """
2057             open preserve@1.0
2058             add file tmp/preserve1 path=testme mode=0644 owner=root group=root preserve=true
2059             close
2060         """
2061 
2062         preserve2 = """
2063             open preserve@2.0
2064             add file tmp/preserve1 path=testme mode=0640 owner=root group=root preserve=true
2065             close
2066         """
2067 
2068         preserve3 = """
2069             open preserve@3.0
2070             add file tmp/preserve3 path=testme mode=0644 owner=root group=root preserve=true
2071             close
2072         """
2073 
2074         preslegacy = """
2075             open preslegacy@1.0
2076             add file tmp/preserve1 path=testme mode=0644 owner=root group=root preserve=true
2077             close
2078             open preslegacy@2.0
2079             add file tmp/preserve2 path=testme mode=0444 owner=root group=root preserve=legacy
2080             close
2081             open preslegacy@3.0
2082             add file tmp/preserve3 path=testme mode=0444 owner=root group=root preserve=legacy
2083             close
2084         """
2085 
2086         renpreslegacy = """
2087             open orig_preslegacy@1.0
2088             add file tmp/preserve1 path=testme mode=0644 owner=root group=root preserve=true
2089             close
2090             open orig_preslegacy@1.1
2091             add set pkg.renamed=true
2092             add depend type=require fmri=ren_preslegacy@2.0
2093             close
2094             open ren_preslegacy@2.0
2095             add file tmp/preserve2 path=newme mode=0444 owner=root group=root preserve=legacy original_name=orig_preslegacy:testme
2096             close
2097         """
2098 
2099         renpreserve = """
2100             open orig_pkg@1.0
2101             add file tmp/preserve1 path=foo1 mode=0644 owner=root group=root preserve=true
2102             add file tmp/bronze1 path=bronze1 mode=0644 owner=root group=root preserve=true
2103             close
2104             open orig_pkg@1.1
2105             add set pkg.renamed=true
2106             add depend type=require fmri=new_pkg@1.0
2107             close
2108             open new_pkg@2.0
2109             add file tmp/preserve3 path=foo2 mode=0644 owner=root group=root original_name=orig_pkg:foo1 preserve=true
2110             add file tmp/bronze1 path=bronze1 mode=0644 owner=root group=root preserve=true
2111             close
2112         """
2113 
2114         linkpreserve = """
2115             open linkpreserve@1.0
2116             add file tmp/preserve1 path=etc/ssh/sshd_config mode=0644 owner=root group=root preserve=true
2117             close
2118             open linkpreserve@2.0
2119             add file tmp/preserve2 path=etc/sunssh/sshd_config mode=0644 owner=root group=root preserve=true original_name=linkpreserve:etc/ssh/sshd_config
2120             add link path=etc/ssh/sshd_config target=../sunssh/sshd_config
2121             close """
2122 
2123         salvage = """
2124             open salvage@1.0
2125             add dir path=var mode=755 owner=root group=root
2126             add dir path=var/mail mode=755 owner=root group=root
2127             add dir path=var/log mode=755 owner=root group=root
2128             add dir path=var/noodles mode=755 owner=root group=root
2129             add dir path=var/persistent mode=755 owner=root group=root
2130             close
2131             open salvage@2.0
2132             add dir path=var mode=755 owner=root group=root
2133             add dir path=var/.migrate-to-shared mode=755 owner=root group=root
2134             add dir path=var/.migrate-to-shared/mail salvage-from=var/mail mode=755 owner=root group=root
2135             add dir path=var/.migrate-to-shared/log salvage-from=var/log mode=755 owner=root group=root
2136             add dir path=var/spaghetti mode=755 owner=root group=root
2137             add dir path=var/persistent mode=755 owner=root group=root salvage-from=var/noodles
2138             close
2139             open salvage@3.0
2140             add dir path=var mode=755 owner=root group=root
2141             add dir path=var/.migrate-to-shared mode=755 owner=root group=root
2142             add dir path=var/.migrate-to-shared/mail salvage-from=var/mail mode=755 owner=root group=root
2143             add dir path=var/.migrate-to-shared/log salvage-from=var/log mode=755 owner=root group=root
2144             add dir path=var/persistent mode=755 owner=root group=root salvage-from=var/noodles salvage-from=var/spaghetti
2145             close
2146         """
2147 
2148         salvage_special = """
2149             open salvage-special@1.0
2150             add dir path=salvage mode=755 owner=root group=root
2151             close
2152         """
2153 
2154         misc_files1 = [
2155             "tmp/amber1", "tmp/amber2", "tmp/bronzeA1",  "tmp/bronzeA2",
2156             "tmp/bronze1", "tmp/bronze2",
2157             "tmp/copyright1", "tmp/copyright2",
2158             "tmp/copyright3", "tmp/copyright4",
2159             "tmp/libc.so.1", "tmp/sh", "tmp/config1", "tmp/config2",
2160             "tmp/gold-passwd1", "tmp/gold-passwd2", "tmp/gold-group",
2161             "tmp/gold-shadow", "tmp/gold-ftpusers", "tmp/gold-silly",
2162             "tmp/silver-silly", "tmp/preserve1", "tmp/preserve2",
2163             "tmp/preserve3", "tmp/renold1", "tmp/renold3", "tmp/rennew1",
2164             "tmp/rennew3", "tmp/liveroot1", "tmp/liveroot2",
2165         ]
2166 
2167         misc_files2 = {
2168             "tmp/dricon_da": """\
2169 wigit "pci8086,1234"
2170 wigit "pci8086,4321"
2171 # someother "pci8086,1234"
2172 foobar "pci8086,9999"
2173 """,
2174             "tmp/dricon2_da": """\
2175 zigit "pci8086,1234"
2176 wigit "pci8086,4321"
2177 # someother "pci8086,1234"
2178 foobar "pci8086,9999"
2179 """,
2180             "tmp/dricon_n2m": """\
2181 wigit 1
2182 foobar 2
2183 """,
2184             "tmp/dripol1_dp": """\
2185 *               read_priv_set=none              write_priv_set=none
2186 """,
2187             "tmp/gold-passwd1": """\
2188 root:x:0:0::/root:/usr/bin/bash
2189 daemon:x:1:1::/:
2190 bin:x:2:2::/usr/bin:
2191 sys:x:3:3::/:
2192 adm:x:4:4:Admin:/var/adm:
2193 """,
2194             "tmp/gold-passwd2": """\
2195 root:x:0:0::/root:/usr/bin/bash
2196 daemon:x:1:1::/:
2197 bin:x:2:2::/usr/bin:
2198 sys:x:3:3::/:
2199 adm:x:4:4:Admin:/var/adm:
2200 bogus:x:10001:10001:Bogus User:/:
2201 """,
2202             "tmp/gold-group": """\
2203 root::0:
2204 other::1:root
2205 bin::2:root,daemon
2206 sys::3:root,bin,adm
2207 adm::4:root,daemon
2208 """,
2209             "tmp/gold-shadow": """\
2210 root:9EIfTNBp9elws:13817::::::
2211 daemon:NP:6445::::::
2212 bin:NP:6445::::::
2213 sys:NP:6445::::::
2214 adm:NP:6445::::::
2215 """,
2216             "tmp/gold-ftpusers": """\
2217 root
2218 bin
2219 sys
2220 adm
2221 """,
2222         }
2223 
2224         cat_data = " "
2225 
2226         foo10 = """
2227             open foo@1.0,5.11-0
2228             close """
2229 
2230         only_attr10 = """
2231             open only_attr@1.0,5.11-0
2232             add set name=foo value=bar
2233             close """
2234 
2235         def setUp(self):
2236                 pkg5unittest.SingleDepotTestCase.setUp(self)
2237                 self.make_misc_files(self.misc_files1)
2238                 self.make_misc_files(self.misc_files2)
2239 
2240         def __salvage_file_contains(self, sroot, fprefix, entry):
2241                 salvaged = [
2242                     n for n in os.listdir(sroot)
2243                     if n.startswith(fprefix + "-")
2244                 ]
2245 
2246                 sfile = os.path.join(sroot, salvaged[0])
2247                 with open(sfile, "rb") as f:
2248                         found = [l.strip() for l in f if entry in l]
2249                         self.assertEqual(found, [entry])
2250 
2251         def test_incorp_install(self):
2252                 """Make sure we don't round up packages we specify on
2253                 install"""
2254 
2255                 first_bronze = self.pkgsend_bulk(self.rurl, self.bronze20)[0]
2256                 self.pkgsend_bulk(self.rurl, (self.incorp20, self.amber10,
2257                     self.bronze10, self.amber20, self.bronze20))
2258 
2259                 # create image
2260                 self.image_create(self.rurl)
2261                 # install incorp2
2262                 self.pkg("install incorp@2.0")
2263                 # try to install version 1
2264                 self.pkg("install bronze@1.0", exit=1)
2265                 # install earliest version bronze@2.0
2266                 self.pkg("install %s" % first_bronze)
2267                 self.pkg("list -v %s" % first_bronze)
2268                 self.pkg("install bronze@2.0")
2269 
2270         def test_upgrade1(self):
2271 
2272                 """ Upgrade torture test.
2273                     Send package amber@1.0, bronze1.0; install bronze1.0, which
2274                     should cause amber to also install.
2275                     Send 2.0 versions of packages which contains a lot of
2276                     complex transactions between amber and bronze, then do
2277                     an update, and try to check the results.
2278                 """
2279 
2280                 # Send 1.0 versions of packages.
2281                 self.pkgsend_bulk(self.rurl, (self.incorp10, self.amber10,
2282                     self.bronze10))
2283 
2284                 #
2285                 # In version 2.0, several things happen:
2286                 #
2287                 # Amber and Bronze swap a file with each other in both
2288                 # directions.  The dependency flips over (Amber now depends
2289                 # on Bronze).  Amber and Bronze swap ownership of various
2290                 # directories.
2291                 #
2292                 # Bronze's 1.0 hardlink to amber's libc goes away and is
2293                 # replaced with a file of the same name.  Amber hardlinks
2294                 # to that.
2295                 #
2296                 self.pkgsend_bulk(self.rurl, (self.incorp20, self.amber20,
2297                     self.bronze20))
2298 
2299                 # create image and install version 1
2300                 self.image_create(self.rurl)
2301                 self.pkg("install incorp@1.0")
2302                 self.file_exists(".SELF-ASSEMBLY-REQUIRED")
2303                 self.pkg("install bronze")
2304 
2305                 self.pkg("list amber@1.0 bronze@1.0")
2306                 self.pkg("verify -v")
2307 
2308                 # demonstrate that incorp@1.0 prevents package movement
2309                 self.pkg("install bronze@2.0 amber@2.0", exit=1)
2310 
2311                 # ...again, but using @latest.
2312                 self.pkg("install bronze@latest amber@latest", exit=1)
2313                 self.pkg("update bronze@latest amber@latest", exit=1)
2314 
2315                 # Now update to get new versions of amber and bronze
2316                 self.file_remove(".SELF-ASSEMBLY-REQUIRED")
2317                 self.pkg("update")
2318                 self.file_exists(".SELF-ASSEMBLY-REQUIRED")
2319 
2320                 # Try to verify that it worked.
2321                 self.pkg("list amber@2.0 bronze@2.0")
2322                 self.pkg("verify -v")
2323                 # make sure old implicit directories for bronzeA1 were removed
2324                 self.assert_(not os.path.isdir(os.path.join(self.get_img_path(),
2325                     "A")))
2326                 # Remove packages
2327                 self.pkg("uninstall amber bronze")
2328                 self.pkg("verify -v")
2329 
2330                 # Make sure all directories are gone save /var in test image.
2331                 self.assertEqual(set(os.listdir(self.get_img_path())),
2332                     set([".SELF-ASSEMBLY-REQUIRED", "var"]))
2333 
2334         def test_upgrade2(self):
2335                 """ test incorporations:
2336                         1) install files that conflict w/ existing incorps
2337                         2) install package w/ dependencies that violate incorps
2338                         3) install incorp that violates existing incorp
2339                         4) install incorp that would force package backwards
2340                         """
2341 
2342                 # Send all pkgs
2343                 self.pkgsend_bulk(self.rurl, (self.incorp10, self.incorp20,
2344                     self.incorp30, self.iridium10, self.concorp10, self.amber10,
2345                     self.amber20, self.bronze10, self.bronze20, self.bronze30,
2346                     self.brass10))
2347 
2348                 self.image_create(self.rurl)
2349 
2350                 self.pkg("install incorp@1.0")
2351                 # install files that conflict w/ existing incorps
2352                 self.pkg("install bronze@2.0", exit=1)
2353                 # install package w/ dependencies that violate incorps
2354                 self.pkg("install iridium@1.0", exit=1)
2355                 # install package w/ unspecified dependency that pulls
2356                 # in bronze
2357                 self.pkg("install brass")
2358                 self.pkg("verify brass@1.0 bronze@1.0")
2359                 # attempt to install conflicting incorporation
2360                 self.pkg("install concorp@1.0", exit=1)
2361 
2362                 # attempt to force downgrade of package w/ older incorp
2363                 self.pkg("install incorp@2.0")
2364                 self.pkg("uninstall incorp@2.0")
2365                 self.pkg("install incorp@1.0", exit=1)
2366 
2367                 # upgrade pkg that loses incorp. deps. in new version
2368                 self.pkg("install incorp@2.0")
2369                 self.pkg("update")
2370                 self.pkg("list bronze@3.0")
2371 
2372         def test_upgrade3(self):
2373                 """Test for editable files moving between packages or locations
2374                 or both."""
2375 
2376                 self.pkgsend_bulk(self.rurl, (self.silver10, self.silver20,
2377                     self.silver30, self.gold10, self.gold20, self.gold30,
2378                     self.golduser10, self.golduser20, self.silveruser))
2379 
2380                 self.image_create(self.rurl)
2381 
2382                 # test 1: move an editable file between packages
2383                 self.pkg("install gold@1.0 silver@1.0")
2384                 self.pkg("verify -v")
2385 
2386                 # modify config file
2387                 test_str = "this file has been modified 1"
2388                 file_path = "etc/passwd"
2389                 self.file_append(file_path, test_str)
2390 
2391                 # make sure /etc/passwd contains correct string
2392                 self.file_contains(file_path, test_str)
2393 
2394                 # update packages
2395                 self.pkg("install gold@3.0 silver@2.0")
2396                 self.pkg("verify -v")
2397 
2398                 # make sure /etc/passwd contains still correct string
2399                 self.file_contains(file_path, test_str)
2400 
2401                 self.pkg("uninstall silver gold")
2402 
2403 
2404                 # test 2: change an editable file's path within a package
2405                 self.pkg("install gold@1.0")
2406                 self.pkg("verify -v")
2407 
2408                 # modify config file
2409                 test_str = "this file has been modified test 2"
2410                 file_path = "etc/passwd"
2411                 self.file_append(file_path, test_str)
2412 
2413                 self.pkg("install gold@2.0")
2414                 self.pkg("verify -v")
2415 
2416                 # make sure /etc/config2 contains correct string
2417                 file_path = "etc/config2"
2418                 self.file_contains(file_path, test_str)
2419 
2420                 self.pkg("uninstall gold")
2421                 self.pkg("verify -v")
2422 
2423 
2424                 # test 3: move an editable file between packages and change its path
2425                 self.pkg("install gold@1.0 silver@1.0")
2426                 self.pkg("verify -v")
2427 
2428                 # modify config file
2429                 file_path = "etc/passwd"
2430                 test_str = "this file has been modified test 3"
2431                 self.file_append(file_path, test_str)
2432 
2433                 self.file_contains(file_path, test_str)
2434 
2435                 self.pkg("install gold@3.0 silver@3.0")
2436                 self.pkg("verify -v")
2437 
2438                 # make sure /etc/config2 now contains correct string
2439                 file_path = "etc/config2"
2440                 self.file_contains(file_path, test_str)
2441 
2442                 self.pkg("uninstall gold silver")
2443 
2444 
2445                 # test 4: move /etc/passwd between packages and ensure that we
2446                 # can still uninstall a user at the same time.
2447                 self.pkg("install gold@1.0 silver@1.0")
2448                 self.pkg("verify -v")
2449 
2450                 # add a user
2451                 self.pkg("install golduser@1.0")
2452 
2453                 # make local changes to the user
2454                 pwdpath = os.path.join(self.get_img_path(), "etc/passwd")
2455 
2456                 pwdfile = file(pwdpath, "r+")
2457                 lines = pwdfile.readlines()
2458                 for i, l in enumerate(lines):
2459                         if l.startswith("Kermit"):
2460                                 lines[i] = lines[i].replace("&amp; User",
2461                                     "Kermit loves Miss Piggy")
2462                 pwdfile.seek(0)
2463                 pwdfile.writelines(lines)
2464                 pwdfile.close()
2465 
2466                 silly_path = os.path.join(self.get_img_path(), "etc/silly")
2467                 silly_inode = os.stat(silly_path).st_ino
2468 
2469                 # update packages
2470                 self.pkg("install gold@3.0 silver@2.0 golduser@2.0 silveruser")
2471 
2472                 # make sure Kermie is still installed and still has our local
2473                 # changes
2474                 self.file_contains("etc/passwd",
2475                     "Kermit:x:5:4:Kermit loves Miss Piggy:/export/home/Kermit:")
2476 
2477                 # also make sure that /etc/silly hasn't been removed and added
2478                 # again, even though it wasn't marked specially
2479                 self.assertEqual(os.stat(silly_path).st_ino, silly_inode)
2480 
2481         def test_upgrade4(self):
2482                 """Test to make sure hardlinks are correctly restored when file
2483                 they point to is updated."""
2484 
2485                 self.pkgsend_bulk(self.rurl, (self.iron10, self.iron20))
2486 
2487                 self.image_create(self.rurl)
2488 
2489                 self.pkg("install iron@1.0")
2490                 self.pkg("verify -v")
2491 
2492                 self.pkg("install iron@2.0")
2493                 self.pkg("verify -v")
2494 
2495         def test_upgrade_liveroot(self):
2496                 """Test to make sure upgrade of package fails if on live root
2497                 and reboot is needed."""
2498 
2499                 self.pkgsend_bulk(self.rurl, (self.liveroot10, self.liveroot20))
2500                 self.image_create(self.rurl)
2501 
2502                 self.pkg("--debug simulate_live_root=%s install liveroot@1.0" %
2503                     self.get_img_path())
2504                 self.pkg("verify -v")
2505                 self.pkg("--debug simulate_live_root=%s install --deny-new-be "
2506                     "liveroot@2.0" % self.get_img_path(), exit=5)
2507                 self.pkg("--debug simulate_live_root=%s uninstall "
2508                     "--deny-new-be liveroot" % self.get_img_path(), exit=5)
2509                 # "break" liveroot@1
2510                 self.file_append("etc/liveroot", "this file has been changed")
2511                 self.pkg("--debug simulate_live_root=%s fix liveroot" %
2512                     self.get_img_path(), exit=5)
2513 
2514         def test_upgrade_driver_conflicts(self):
2515                 """Test to make sure driver_aliases conflicts don't cause
2516                 add_drv to fail."""
2517 
2518                 self.pkgsend_bulk(self.rurl, (self.dricon1, self.dricon2,
2519                     self.dricon3))
2520 
2521                 self.image_create(self.rurl)
2522 
2523                 self.pkg("list -afv")
2524                 self.pkg("install dricon@1")
2525                 # This one should comment out the wigit entry in driver_aliases
2526                 self.pkg("install dricon@2")
2527                 da_contents = file(os.path.join(self.get_img_path(),
2528                     "etc/driver_aliases")).readlines()
2529                 self.assert_("# pkg(5): wigit \"pci8086,1234\"\n" in da_contents)
2530                 self.assert_("wigit \"pci8086,1234\"\n" not in da_contents)
2531                 self.assert_("wigit \"pci8086,4321\"\n" in da_contents)
2532                 self.assert_("zigit \"pci8086,1234\"\n" in da_contents)
2533                 # This one should fail
2534                 self.pkg("install dricon@3", exit=1)
2535 
2536         def test_driver_policy_removal(self):
2537                 """Test for bug #9568 - that removing a policy for a
2538                 driver where there is no minor node associated with it,
2539                 works successfully.
2540                 """
2541 
2542                 self.pkgsend_bulk(self.rurl, (self.dripol1, self.dripol2))
2543 
2544                 self.image_create(self.rurl)
2545 
2546                 self.pkg("list -afv")
2547 
2548                 # Should install the frigit driver with a policy.
2549                 self.pkg("install dripol@1")
2550 
2551                 # Check that there is a policy entry for this
2552                 # device in /etc/security/device_policy
2553                 dp_contents = file(os.path.join(self.get_img_path(),
2554                     "etc/security/device_policy")).readlines()
2555                 self.assert_("frigit:*\tread_priv_set=net_rawaccess\twrite_priv_set=net_rawaccess\n" in dp_contents)
2556 
2557                 # Should reinstall the frigit driver without a policy.
2558                 self.pkg("install dripol@2")
2559 
2560                 # Check that there is no longer a policy entry for this
2561                 # device in /etc/security/device_policy
2562                 dp_contents = file(os.path.join(self.get_img_path(),
2563                     "etc/security/device_policy")).readlines()
2564                 self.assert_("frigit:*\tread_priv_set=net_rawaccess\twrite_priv_set=net_rawaccess\n" not in dp_contents)
2565 
2566         def test_file_preserve(self):
2567                 """Verify that file preserve=true works as expected during
2568                 package install, update, upgrade, and removal."""
2569 
2570                 self.pkgsend_bulk(self.rurl, (self.preserve1, self.preserve2,
2571                     self.preserve3, self.renpreserve))
2572                 self.image_create(self.rurl)
2573 
2574                 # If there are no local modifications, no preservation should be
2575                 # done.  First with no content change ...
2576                 self.pkg("install preserve@1")
2577                 self.pkg("install preserve@2")
2578                 self.file_contains("testme", "preserve1")
2579                 self.pkg("verify preserve")
2580 
2581                 self.pkg("update preserve@1")
2582                 self.file_contains("testme", "preserve1")
2583                 self.pkg("verify preserve")
2584 
2585                 self.pkg("uninstall preserve")
2586 
2587                 # ... and again with content change.
2588                 self.pkg("install preserve@1")
2589                 self.pkg("install preserve@3")
2590                 self.file_contains("testme", "preserve3")
2591 
2592                 self.pkg("update preserve@1")
2593                 self.file_contains("testme", "preserve1")
2594 
2595                 self.pkg("verify preserve")
2596                 self.pkg("uninstall preserve")
2597 
2598                 # Modify the file locally and update to a version where the
2599                 # content changes.
2600                 self.pkg("install preserve@1")
2601                 self.file_append("testme", "junk")
2602                 self.file_contains("testme", "preserve1")
2603                 self.pkg("install preserve@3")
2604                 self.file_contains("testme", "preserve1")
2605                 self.file_contains("testme", "junk")
2606                 self.file_doesnt_exist("testme.old")
2607                 self.file_doesnt_exist("testme.new")
2608                 self.pkg("verify preserve")
2609                 self.pkg("uninstall preserve")
2610 
2611                 # Modify the file locally and downgrade to a version where
2612                 # the content changes.
2613                 self.pkg("install preserve@3")
2614                 self.file_append("testme", "junk")
2615                 self.file_contains("testme", "preserve3")
2616                 self.pkg("update preserve@1")
2617                 self.file_doesnt_contain("testme", "preserve3")
2618                 self.file_doesnt_contain("testme", "junk")
2619                 self.file_doesnt_exist("testme.old")
2620                 self.file_doesnt_exist("testme.new")
2621                 self.file_exists("testme.update")
2622                 self.file_remove("testme.update")
2623                 self.pkg("verify preserve")
2624                 self.pkg("uninstall preserve")
2625 
2626                 # Modify the file locally and update to a version where just the
2627                 # mode changes.
2628                 self.pkg("install preserve@1")
2629                 self.file_append("testme", "junk")
2630 
2631                 self.pkg("install preserve@2")
2632                 self.file_contains("testme", "preserve1")
2633                 self.file_contains("testme", "junk")
2634                 self.file_doesnt_exist("testme.old")
2635                 self.file_doesnt_exist("testme.new")
2636 
2637                 self.pkg("update preserve@1")
2638                 self.file_contains("testme", "preserve1")
2639                 self.file_contains("testme", "junk")
2640                 self.file_doesnt_exist("testme.old")
2641                 self.file_doesnt_exist("testme.new")
2642                 self.file_doesnt_exist("testme.update")
2643 
2644                 self.pkg("install preserve@2")
2645                 self.file_doesnt_exist("testme.old")
2646                 self.file_doesnt_exist("testme.new")
2647 
2648                 # Remove the file locally and update the package; this should
2649                 # simply replace the missing file.
2650                 self.file_remove("testme")
2651                 self.pkg("install preserve@3")
2652                 self.pkg("verify preserve")
2653                 self.file_exists("testme")
2654 
2655                 # Remove the file locally and downgrade the package; this should
2656                 # simply replace the missing file.
2657                 self.file_remove("testme")
2658                 self.pkg("update preserve@2")
2659                 self.pkg("verify preserve")
2660                 self.file_exists("testme")
2661                 self.pkg("uninstall preserve@2")
2662 
2663                 # Preserved files don't get their mode changed, and verify will
2664                 # still balk, so fix up the mode.
2665                 self.pkg("install preserve@1")
2666                 self.pkg("install preserve@2")
2667                 self.file_chmod("testme", 0640)
2668                 self.pkg("verify preserve")
2669 
2670                 # Verify that a package with a missing file that is marked with
2671                 # the preserve=true won't cause uninstall failure.
2672                 self.file_remove("testme")
2673                 self.file_doesnt_exist("testme")
2674                 self.pkg("uninstall preserve")
2675 
2676                 # Verify preserve works across package rename with and without
2677                 # original_name use and even when the original file is missing.
2678                 self.pkg("install orig_pkg@1.0")
2679                 foo1_path = os.path.join(self.get_img_path(), "foo1")
2680                 self.assert_(os.path.isfile(foo1_path))
2681                 bronze1_path = os.path.join(self.get_img_path(), "bronze1")
2682                 self.assert_(os.path.isfile(bronze1_path))
2683 
2684                 # Update across the rename boundary, then verify that the files
2685                 # were installed with their new name and the old ones were
2686                 # removed.
2687                 self.pkg("update orig_pkg")
2688                 foo2_path = os.path.join(self.get_img_path(), "foo2")
2689                 self.assert_(not os.path.exists(foo1_path))
2690                 self.assert_(os.path.isfile(foo2_path))
2691                 self.assert_(os.path.isfile(bronze1_path))
2692                 self.pkg("uninstall \*")
2693 
2694                 # Update across the rename boundary, then truncate each of the
2695                 # preserved files.  They should remain empty even though one is
2696                 # changing names and the other is simply being preserved across
2697                 # a package rename.
2698                 self.pkg("install orig_pkg@1.0")
2699                 open(foo1_path, "wb").close()
2700                 open(bronze1_path, "wb").close()
2701                 self.pkg("update orig_pkg")
2702                 self.assert_(not os.path.exists(foo1_path))
2703                 self.assert_(os.path.isfile(foo2_path))
2704                 self.assertEqual(os.stat(foo2_path).st_size, 0)
2705                 self.assert_(os.path.isfile(bronze1_path))
2706                 self.assertEqual(os.stat(bronze1_path).st_size, 0)
2707                 self.pkg("uninstall \*")
2708 
2709                 # Update across the rename boundary, then verify that a change
2710                 # in file name will cause re-delivery of preserved files, but
2711                 # unchanged, preserved files will not be re-delivered.
2712                 self.pkg("install orig_pkg@1.0")
2713                 os.unlink(foo1_path)
2714                 os.unlink(bronze1_path)
2715                 self.pkg("update orig_pkg")
2716                 self.assert_(not os.path.exists(foo1_path))
2717                 self.assert_(os.path.isfile(foo2_path))
2718                 self.assert_(not os.path.exists(bronze1_path))
2719                 self.pkg("uninstall \*")
2720 
2721                 # Ensure directory is empty before testing.
2722                 api_inst = self.get_img_api_obj()
2723                 img_inst = api_inst.img
2724                 sroot = os.path.join(img_inst.imgdir, "lost+found")
2725                 shutil.rmtree(sroot)
2726 
2727                 # Verify that unmodified, preserved files will not be salvaged
2728                 # on uninstall.
2729                 self.pkg("install preserve@1.0")
2730                 self.file_contains("testme", "preserve1")
2731                 self.pkg("uninstall preserve")
2732                 salvaged = [
2733                     n for n in os.listdir(sroot)
2734                     if n.startswith("testme-")
2735                 ]
2736                 self.assertEqual(salvaged, [])
2737 
2738                 # Verify that modified, preserved files will be salvaged
2739                 # on uninstall.
2740                 self.pkg("install preserve@1.0")
2741                 self.file_contains("testme", "preserve1")
2742                 self.file_append("testme", "junk")
2743                 self.pkg("uninstall preserve")
2744                 self.__salvage_file_contains(sroot, "testme", "junk")
2745 
2746         def test_file_preserve_renameold(self):
2747                 """Make sure that file upgrade with preserve=renameold works."""
2748 
2749                 plist = self.pkgsend_bulk(self.rurl, (self.renameold1,
2750                     self.renameold2, self.renameold3))
2751                 self.image_create(self.rurl)
2752 
2753                 # If there are no local modifications, no preservation should be
2754                 # done.  First with no content change ...
2755                 self.pkg("install renold@1")
2756                 self.pkg("install renold@2")
2757                 self.file_contains("testme", "renold1")
2758                 self.file_doesnt_exist("testme.old")
2759                 self.file_doesnt_exist("testme.new")
2760                 self.pkg("verify renold")
2761                 self.pkg("uninstall renold")
2762 
2763                 # ... and again with content change.
2764                 self.pkg("install renold@1")
2765                 self.pkg("install renold@3")
2766                 self.file_contains("testme", "renold3")
2767                 self.file_doesnt_exist("testme.old")
2768                 self.file_doesnt_exist("testme.new")
2769                 self.pkg("verify renold")
2770                 self.pkg("uninstall renold")
2771 
2772                 # Modify the file locally and update to a version where the
2773                 # content changes.
2774                 self.pkg("install renold@1")
2775                 self.file_append("testme", "junk")
2776                 self.pkg("install renold@3")
2777                 self.file_contains("testme.old", "junk")
2778                 self.file_doesnt_contain("testme", "junk")
2779                 self.file_contains("testme", "renold3")
2780                 self.dest_file_valid(plist, "renold@3.0", "testme", "testme")
2781                 self.file_doesnt_exist("testme.new")
2782                 self.pkg("verify renold")
2783                 self.pkg("uninstall renold")
2784 
2785                 # Modify the file locally and update to a version where just the
2786                 # mode changes.
2787                 self.pkg("install renold@1")
2788                 self.file_append("testme", "junk")
2789                 self.pkg("install renold@2")
2790                 self.file_contains("testme.old", "junk")
2791                 self.file_doesnt_contain("testme", "junk")
2792                 self.file_contains("testme", "renold1")
2793                 self.file_doesnt_exist("testme.new")
2794                 self.pkg("verify renold")
2795                 self.pkg("uninstall renold")
2796 
2797                 # Remove the file locally and update the package; this should
2798                 # simply replace the missing file.
2799                 self.pkg("install renold@1")
2800                 self.file_remove("testme")
2801                 self.pkg("install renold@2")
2802                 self.pkg("verify renold")
2803                 self.pkg("uninstall renold")
2804 
2805         def test_file_preserve_renamenew(self):
2806                 """Make sure that file ugprade with preserve=renamenew works."""
2807 
2808                 plist = self.pkgsend_bulk(self.rurl, (self.renamenew1,
2809                     self.renamenew2, self.renamenew3))
2810                 self.image_create(self.rurl)
2811 
2812                 # If there are no local modifications, no preservation should be
2813                 # done.  First with no content change ...
2814                 self.pkg("install rennew@1")
2815                 self.pkg("install rennew@2")
2816                 self.file_contains("testme", "rennew1")
2817                 self.file_doesnt_exist("testme.new")
2818                 self.file_doesnt_exist("testme.old")
2819                 self.pkg("verify rennew")
2820                 self.pkg("uninstall rennew")
2821 
2822                 # ... and again with content change
2823                 self.pkg("install rennew@1")
2824                 self.pkg("install rennew@3")
2825                 self.file_contains("testme", "rennew3")
2826                 self.file_doesnt_exist("testme.new")
2827                 self.file_doesnt_exist("testme.old")
2828                 self.pkg("verify rennew")
2829                 self.pkg("uninstall rennew")
2830 
2831                 # Modify the file locally and update to a version where the
2832                 # content changes.
2833                 self.pkg("install rennew@1")
2834                 self.file_append("testme", "junk")
2835                 self.pkg("install rennew@3")
2836                 self.file_contains("testme", "junk")
2837                 self.file_doesnt_contain("testme.new", "junk")
2838                 self.file_contains("testme.new", "rennew3")
2839                 self.dest_file_valid(plist, "rennew@3.0", "testme",
2840                     "testme.new")
2841                 self.file_doesnt_exist("testme.old")
2842                 self.pkg("verify rennew")
2843                 self.pkg("uninstall rennew")
2844 
2845                 # Modify the file locally and update to a version where just the
2846                 # mode changes.
2847                 self.pkg("install rennew@1")
2848                 self.file_append("testme", "junk")
2849                 self.pkg("install rennew@2")
2850                 self.file_contains("testme", "junk")
2851                 self.file_doesnt_contain("testme.new", "junk")
2852                 self.file_contains("testme.new", "rennew1")
2853                 self.file_doesnt_exist("testme.old")
2854 
2855                 # Preserved files don't get their mode changed, and verify will
2856                 # still balk, so fix up the mode.
2857                 self.file_chmod("testme", 0640)
2858                 self.pkg("verify rennew")
2859                 self.pkg("uninstall rennew")
2860                 self.file_remove("testme.new")
2861 
2862                 # Remove the file locally and update the package; this should
2863                 # simply replace the missing file.
2864                 self.pkg("install rennew@1")
2865                 self.file_remove("testme")
2866                 self.pkg("install rennew@2")
2867                 self.file_doesnt_exist("testme.new")
2868                 self.file_doesnt_exist("testme.old")
2869                 self.pkg("verify rennew")
2870                 self.pkg("uninstall rennew")
2871 
2872         def test_file_preserve_legacy(self):
2873                 """Verify that preserve=legacy works as expected."""
2874 
2875                 self.pkgsend_bulk(self.rurl, (self.preslegacy,
2876                     self.renpreslegacy))
2877                 self.image_create(self.rurl)
2878 
2879                 # Ensure directory is empty before testing.
2880                 api_inst = self.get_img_api_obj()
2881                 img_inst = api_inst.img
2882                 sroot = os.path.join(img_inst.imgdir, "lost+found")
2883                 shutil.rmtree(sroot)
2884 
2885                 # Verify that unpackaged files will be salvaged on initial
2886                 # install if a package being installed delivers the same file
2887                 # and that the new file will be installed.
2888                 self.file_append("testme", "unpackaged")
2889                 self.pkg("install preslegacy@1.0")
2890                 self.file_contains("testme", "preserve1")
2891                 self.__salvage_file_contains(sroot, "testme", "unpackaged")
2892                 shutil.rmtree(sroot)
2893 
2894                 # Verify that a package transitioning to preserve=legacy from
2895                 # some other state will have the existing file renamed using
2896                 # .legacy as an extension.
2897                 self.pkg("update preslegacy@2.0")
2898                 self.file_contains("testme.legacy", "preserve1")
2899                 self.file_contains("testme", "preserve2")
2900 
2901                 # Verify that if an action with preserve=legacy is upgraded
2902                 # and its payload changes that the new payload is delivered
2903                 # but the old .legacy file is not modified.
2904                 self.pkg("update preslegacy@3.0")
2905                 self.file_contains("testme.legacy", "preserve1")
2906                 self.file_contains("testme", "preserve3")
2907 
2908                 # Verify that if the file for an action marked with
2909                 # preserve=legacy is removed that the package still
2910                 # verifies.
2911                 self.file_remove("testme")
2912                 self.pkg("verify -v preslegacy")
2913 
2914                 # Verify that a file removed for an action marked with
2915                 # preserve=legacy can be reverted.
2916                 self.pkg("revert testme")
2917                 self.file_contains("testme", "preserve3")
2918 
2919                 # Verify that an initial install of an action with
2920                 # preserve=legacy will not install the payload of the action.
2921                 self.pkg("uninstall preslegacy")
2922                 self.pkg("install preslegacy@3.0")
2923                 self.file_doesnt_exist("testme")
2924 
2925                 # Verify that if the original preserved file is missing during
2926                 # a transition to preserve=legacy from some other state that
2927                 # the new action is still delivered and the operation succeeds.
2928                 self.pkg("uninstall preslegacy")
2929                 self.pkg("install preslegacy@1.0")
2930                 self.file_remove("testme")
2931                 self.pkg("update")
2932                 self.file_contains("testme", "preserve3")
2933 
2934                 # Verify that a preserved file can be moved from one package to
2935                 # another and transition to preserve=legacy at the same time.
2936                 self.pkg("uninstall preslegacy")
2937                 self.pkg("install orig_preslegacy@1.0")
2938                 self.file_exists("testme")
2939                 self.pkg("update")
2940                 self.file_contains("testme.legacy", "preserve1")
2941                 self.file_contains("newme", "preserve2")
2942 
2943         def test_directory_salvage(self):
2944                 """Make sure basic directory salvage works as expected"""
2945                 self.pkgsend_bulk(self.rurl, self.salvage)
2946                 self.image_create(self.rurl)
2947                 self.pkg("install salvage@1.0")
2948                 self.file_append("var/mail/foo", "foo's mail")
2949                 self.file_append("var/mail/bar", "bar's mail")
2950                 self.file_append("var/mail/baz", "baz's mail")
2951                 self.pkg("update salvage")
2952                 self.file_exists("var/.migrate-to-shared/mail/foo")
2953                 self.file_exists("var/.migrate-to-shared/mail/bar")
2954                 self.file_exists("var/.migrate-to-shared/mail/baz")
2955 
2956         def test_directory_salvage_persistent(self):
2957                 """Make sure directory salvage works as expected when salvaging
2958                 content to an existing packaged directory."""
2959 
2960                 # we salvage content from two directories,
2961                 # var/noodles and var/spaghetti each of which disappear over
2962                 # subsequent updates.
2963                 self.pkgsend_bulk(self.rurl, self.salvage)
2964                 self.image_create(self.rurl)
2965                 self.pkg("install salvage@1.0")
2966                 self.file_append("var/mail/foo", "foo's mail")
2967                 self.file_append("var/noodles/noodles.txt", "yum")
2968                 self.pkg("update salvage@2.0")
2969                 self.file_exists("var/.migrate-to-shared/mail/foo")
2970                 self.file_exists("var/persistent/noodles.txt")
2971                 self.file_append("var/spaghetti/spaghetti.txt", "yum")
2972                 self.pkg("update")
2973                 self.file_exists("var/persistent/noodles.txt")
2974                 self.file_exists("var/persistent/spaghetti.txt")
2975 
2976                 # ensure that we can jump from 1.0 to 3.0 directly.
2977                 self.image_create(self.rurl)
2978                 self.pkg("install salvage@1.0")
2979                 self.file_append("var/noodles/noodles.txt", "yum")
2980                 self.pkg("update  salvage@3.0")
2981                 self.file_exists("var/persistent/noodles.txt")
2982 
2983         def test_special_salvage(self):
2984                 """Make sure salvaging directories with special files works as
2985                 expected."""
2986                 self.pkgsend_bulk(self.rurl, self.salvage_special)
2987                 self.image_create(self.rurl, destroy=True, fs=("var",))
2988 
2989                 self.pkg("install salvage-special")
2990 
2991                 os.mkfifo(os.path.join(self.img_path(), "salvage", "fifo"))
2992                 sock = socket.socket(socket.AF_UNIX)
2993                 sock.bind(os.path.join(self.img_path(), "salvage", "socket"))
2994                 sock.close()
2995                 # We also test block and character special files, but only if
2996                 # os.mknod() is available, which it isn't always.
2997                 if hasattr(os, "mknod"):
2998                         st = os.stat("/dev/null")
2999                         os.mknod(os.path.join(self.img_path(), "salvage",
3000                             "node"), st.st_mode, st.st_dev)
3001 
3002                 # This could hang reading fifo, or keel over reading socket.
3003                 self.pkg("uninstall salvage-special")
3004 
3005         def dest_file_valid(self, plist, pkg, src, dest):
3006                 """Used to verify that the dest item's mode, attrs, timestamp,
3007                 etc. match the src items's matching action as expected."""
3008 
3009                 for p in plist:
3010                         pfmri = fmri.PkgFmri(p, "5.11")
3011                         pfmri.publisher = None
3012                         sfmri = pfmri.get_short_fmri().replace("pkg:/", "")
3013 
3014                         if pkg != sfmri:
3015                                 continue
3016 
3017                         m = manifest.Manifest()
3018                         m.set_content(self.get_img_manifest(pfmri))
3019                         for a in m.gen_actions():
3020                                 if a.name != "file":
3021                                         # Only want file actions that have
3022                                         # preserve attribute.
3023                                         continue
3024                                 if a.attrs["path"] != src:
3025                                         # Only want actions with matching path.
3026                                         continue
3027                                 self.validate_fsobj_attrs(a, target=dest)
3028 
3029         def test_link_preserve(self):
3030                 """Ensure that files transitioning to a link still follow
3031                 original_name preservation rules."""
3032 
3033                 self.pkgsend_bulk(self.rurl, (self.linkpreserve))
3034                 self.image_create(self.rurl, destroy=True, fs=("var",))
3035 
3036                 # Install package with original config file location.
3037                 self.pkg("install linkpreserve@1.0")
3038                 cfg_path = os.path.join("etc", "ssh", "sshd_config")
3039                 abs_path = os.path.join(self.get_img_path(), cfg_path)
3040 
3041                 self.file_exists(cfg_path)
3042                 self.assert_(not os.path.islink(abs_path))
3043 
3044                 # Modify the file.
3045                 self.file_append(cfg_path, "modified")
3046 
3047                 # Install new package version, verify file replaced with link
3048                 # and modified version was moved to new location.
3049                 new_cfg_path = os.path.join("etc", "sunssh", "sshd_config")
3050                 self.pkg("update linkpreserve@2.0")
3051                 self.assert_(os.path.islink(abs_path))
3052                 self.file_exists(new_cfg_path)
3053                 self.file_contains(new_cfg_path, "modified")
3054 
3055                 # Uninstall, then install original version again.
3056                 self.pkg("uninstall linkpreserve")
3057                 self.pkg("install linkpreserve@1.0")
3058                 self.file_contains(cfg_path, "preserve1")
3059 
3060                 # Install new package version and verify that unmodified file is
3061                 # replaced with new configuration file.
3062                 self.pkg("update linkpreserve@2.0")
3063                 self.file_contains(new_cfg_path, "preserve2")
3064 
3065 
3066 class TestPkgInstallActions(pkg5unittest.SingleDepotTestCase):
3067         # Only start/stop the depot once (instead of for every test)
3068         persistent_setup = True
3069 
3070         misc_files = {
3071                 "ftpusers" :
3072 """# ident      "@(#)ftpusers   1.6     06/11/21 SMI"
3073 #
3074 # List of users denied access to the FTP server, see ftpusers(4).
3075 #
3076 root
3077 bin
3078 sys
3079 adm
3080 """,
3081                 "group" :
3082 """root::0:
3083 other::1:root
3084 bin::2:root,daemon
3085 sys::3:root,bin,adm
3086 adm::4:root,daemon
3087 +::::
3088 """,
3089                 "passwd" :
3090 """root:x:0:0::/root:/usr/bin/bash
3091 daemon:x:1:1::/:
3092 bin:x:2:2::/usr/bin:
3093 sys:x:3:3::/:
3094 adm:x:4:4:Admin:/var/adm:
3095 +::::::
3096 """,
3097                 "shadow" :
3098 """root:9EIfTNBp9elws:13817::::::
3099 daemon:NP:6445::::::
3100 bin:NP:6445::::::
3101 sys:NP:6445::::::
3102 adm:NP:6445::::::
3103 +::::::::
3104 """,
3105                 "cat" : " ",
3106                 "empty" : ""
3107         }
3108 
3109 
3110         foo10 = """
3111             open foo@1.0,5.11-0
3112             close """
3113 
3114         only_attr10 = """
3115             open only_attr@1.0,5.11-0
3116             add set name=foo value=bar
3117             close """
3118 
3119         only_depend10 = """
3120             open only_depend@1.0,5.11-0
3121             add depend type=require fmri=foo@1.0,5.11-0
3122             close """
3123 
3124         only_directory10 = """
3125             open only_dir@1.0,5.11-0
3126             add dir mode=0755 owner=root group=bin path=/bin
3127             close """
3128 
3129         only_driver10 = """
3130             open only_driver@1.0,5.11-0
3131             add driver name=zerg devlink="type=ddi_pseudo;name=zerg\\t\D"
3132             close """
3133 
3134         only_group10 = """
3135             open only_group@1.0,5.11-0
3136             add group groupname=Kermit gid=28
3137             close """
3138 
3139         only_group_file10 = """
3140             open only_group_file@1.0,5.11-0
3141             add dir mode=0755 owner=root group=Kermit path=/export/home/Kermit
3142             close """
3143 
3144         only_hardlink10 = """
3145             open only_hardlink@1.0,5.11-0
3146             add hardlink path=/cat.hardlink target=/cat
3147             close """
3148 
3149         only_legacy10 = """
3150             open only_legacy@1.0,5.11-0
3151             add legacy category=system desc="GNU make - A utility used to build software (gmake) 3.81" hotline="Please contact your local service provider" name="gmake - GNU make" pkg=SUNWgmake vendor="Sun Microsystems, Inc." version=11.11.0,REV=2008.04.29.02.08
3152             close """
3153 
3154         only_link10 = """
3155             open only_link@1.0,5.11-0
3156             add link path=/link target=/tmp/cat
3157             close """
3158 
3159         only_user10 = """
3160             open only_user@1.0,5.11-0
3161             add user username=Kermit group=adm home-dir=/export/home/Kermit
3162             close """
3163 
3164         only_user_file10 = """
3165             open only_user_file@1.0,5.11-0
3166             add dir mode=0755 owner=Kermit group=adm path=/export/home/Kermit
3167             close """
3168 
3169         csu1 = """
3170             open csu1@1.0,5.11-0
3171             add legacy category=system desc="core software for a specific instruction-set architecture" hotline="Please contact your local service provider" name="Core Solaris, (Usr)" pkg=SUNWcsu vendor="Oracle Corporation" version=11.11,REV=2009.11.11
3172             close
3173         """
3174 
3175         csu1_2 = """
3176             open csu1@2.0,5.11-0
3177             add legacy category=system desc="core software for a specific instruction-set architecture" hotline="Please contact your local service provider" name="Core Solaris, (Usr)" pkg=SUNWcsu vendor="Oracle Corporation" version=11.11,REV=2010.11.11
3178             close
3179         """
3180 
3181         csu2 = """
3182             open csu2@1.0,5.11-0
3183             add legacy category=system desc="core software for a specific instruction-set architecture" hotline="Please contact your local service provider" name="Core Solaris, (Usr)" pkg=SUNWcsu vendor="Oracle Corporation" version=11.11,REV=2009.11.11
3184             close
3185         """
3186 
3187         csu2_2 = """
3188             open csu2@2.0,5.11-0
3189             add legacy category=system desc="core software for a specific instruction-set architecture" hotline="Please contact your local service provider" name="Core Solaris, (Usr)" pkg=SUNWcsu vendor="Oracle Corporation" version=11.11,REV=2010.11.11
3190             close
3191         """
3192 
3193         csu3 = """
3194             open csu3@1.0,5.11-0
3195             add legacy category=system desc="core software for a specific instruction-set architecture" hotline="Please contact your local service provider" name="Core Solaris, (Usr)" pkg=SUNWcsu vendor="Oracle Corporation" version=11.11,REV=2009.11.11
3196             close
3197         """
3198 
3199         csu3_2 = """
3200             open csu3@2.0,5.11-0
3201             add legacy category=system desc="core software for a specific instruction-set architecture" hotline="Please contact your local service provider" name="Core Solaris, (Usr)" pkg=SUNWcsu vendor="Oracle Corporation" version=11.11,REV=2010.11.11
3202             close
3203         """
3204 
3205         # some of these are subsets-- "always" and "at-end"-- for performance;
3206         # we assume that e.g. if a and z work, that bcdef, etc. will too.
3207         pkg_name_valid_chars = {
3208             "never": " `~!@#$%^&amp;*()=[{]}\\|;:\",&lt;&gt;?",
3209             "always": "09azAZ",
3210             "after-first": "_-.+",
3211             "at-end": "09azAZ_-.+",
3212         }
3213 
3214         def setUp(self):
3215 
3216                 pkg5unittest.SingleDepotTestCase.setUp(self)
3217 
3218                 self.only_file10 = """
3219                     open only_file@1.0,5.11-0
3220                     add file cat mode=0555 owner=root group=bin path=/cat
3221                     close """
3222 
3223                 self.only_license10 = """
3224                     open only_license@1.0,5.11-0
3225                     add license cat license=copyright
3226                     close """
3227 
3228                 self.baseuser = """
3229                     open system/action/user@0,5.11
3230                     add dir path=etc mode=0755 owner=root group=sys
3231                     add dir path=etc/ftpd mode=0755 owner=root group=sys
3232                     add user username=root password=9EIfTNBp9elws uid=0 group=root home-dir=/root gcos-field=Super-User login-shell=/usr/bin/bash ftpuser=false lastchg=13817 group-list=other group-list=bin group-list=sys group-list=adm
3233                     add group gid=0 groupname=root
3234                     add group gid=3 groupname=sys
3235                     add file empty path=etc/group mode=0644 owner=root group=sys preserve=true
3236                     add file empty path=etc/passwd mode=0644 owner=root group=sys preserve=true
3237                     add file empty path=etc/shadow mode=0400 owner=root group=sys preserve=true
3238                     add file empty path=etc/ftpd/ftpusers mode=0644 owner=root group=sys preserve=true
3239                     add file empty path=etc/user_attr mode=0644 owner=root group=sys preserve=true
3240                     close """
3241 
3242                 self.singleuser = """
3243                     open singleuser@0,5.11
3244                     add user group=fozzie uid=16 username=fozzie
3245                     add group groupname=fozzie gid=16
3246                     close
3247                 """
3248 
3249                 self.basics0 = """
3250                     open basics@1.0,5.11-0
3251                     add file passwd mode=0644 owner=root group=sys path=etc/passwd preserve=true
3252                     add file shadow mode=0400 owner=root group=sys path=etc/shadow preserve=true
3253                     add file group mode=0644 owner=root group=sys path=etc/group preserve=true
3254                     add file ftpusers mode=0644 owner=root group=sys path=etc/ftpd/ftpusers preserve=true
3255                     add dir mode=0755 owner=root group=sys path=etc
3256                     add dir mode=0755 owner=root group=sys path=etc/ftpd
3257                     close """
3258 
3259                 self.basics1 = """
3260                     open basics1@1.0,5.11-0
3261                     add dir mode=0755 owner=root group=bin path=lib
3262                     add dir mode=0755 owner=root group=sys path=var
3263                     add dir mode=0755 owner=root group=sys path=var/svc
3264                     add dir mode=0755 owner=root group=sys path=var/svc/manifest
3265                     add dir mode=0755 owner=root group=bin path=usr
3266                     add dir mode=0755 owner=root group=bin path=usr/local
3267                     close """
3268 
3269                 self.grouptest = """
3270                     open grouptest@1.0,5.11-0
3271                     add dir mode=0755 owner=root group=Kermit path=/usr/Kermit
3272                     add file empty mode=0755 owner=root group=Kermit path=/usr/local/bin/do_group_nothing
3273                     add group groupname=lp gid=8
3274                     add group groupname=staff gid=10
3275                     add group groupname=Kermit
3276                     add depend fmri=pkg:/basics@1.0 type=require
3277                     close """
3278 
3279                 self.usertest10 = """
3280                     open usertest@1.0,5.11-0
3281                     add dir mode=0755 owner=Kermit group=Kermit path=/export/home/Kermit
3282                     add file empty mode=0755 owner=Kermit group=Kermit path=/usr/local/bin/do_user_nothing
3283                     add depend fmri=pkg:/basics@1.0 type=require
3284                     add user username=Kermit group=Kermit home-dir=/export/home/Kermit group-list=lp group-list=staff
3285                     add depend fmri=pkg:/grouptest@1.0 type=require
3286                     add depend fmri=pkg:/basics@1.0 type=require
3287                     close """
3288 
3289                 self.usertest11 = """
3290                     open usertest@1.1,5.11-0
3291                     add dir mode=0755 owner=Kermit group=Kermit path=/export/home/Kermit
3292                     add file empty mode=0755 owner=Kermit group=Kermit path=/usr/local/bin/do_user_nothing
3293                     add depend fmri=pkg:/basics@1.0 type=require
3294                     add user username=Kermit group=Kermit home-dir=/export/home/Kermit2 group-list=lp group-list=staff group-list=root ftpuser=false
3295                     add depend fmri=pkg:/grouptest@1.0 type=require
3296                     add depend fmri=pkg:/basics@1.0 type=require
3297                     close """
3298 
3299                 self.ugidtest = """
3300                     open ugidtest@1.0,5.11-0
3301                     add user username=dummy group=root
3302                     add group groupname=dummy
3303                     close """
3304 
3305                 self.silver10 = """
3306                     open silver@1.0,5.11-0
3307                     add file empty mode=0755 owner=root group=root path=/usr/local/bin/silver
3308                     add depend fmri=pkg:/basics@1.0 type=require
3309                     add depend fmri=pkg:/basics1@1.0 type=require
3310                     close """
3311                 self.silver20 = """
3312                     open silver@2.0,5.11-0
3313                     add file empty mode=0755 owner=Kermit group=Kermit path=/usr/local/bin/silver
3314                     add user username=Kermit group=Kermit home-dir=/export/home/Kermit group-list=lp group-list=staff
3315                     add depend fmri=pkg:/basics@1.0 type=require
3316                     add depend fmri=pkg:/basics1@1.0 type=require
3317                     add depend fmri=pkg:/grouptest@1.0 type=require
3318                     close """
3319 
3320                 self.devicebase = """
3321                     open devicebase@1.0,5.11-0
3322                     add dir mode=0755 owner=root group=sys path=/var
3323                     add dir mode=0755 owner=root group=sys path=/var/run
3324                     add dir mode=0755 owner=root group=root path=system
3325                     add dir mode=0755 owner=root group=root path=system/volatile
3326                     add dir mode=0755 owner=root group=sys path=/tmp
3327                     add dir mode=0755 owner=root group=sys path=/etc
3328                     add dir mode=0755 owner=root group=sys path=/etc/security
3329                     add file empty mode=0600 owner=root group=sys path=/etc/devlink.tab preserve=true
3330                     add file empty mode=0644 owner=root group=sys path=/etc/name_to_major preserve=true
3331                     add file empty mode=0644 owner=root group=sys path=/etc/driver_aliases preserve=true
3332                     add file empty mode=0644 owner=root group=sys path=/etc/driver_classes preserve=true
3333                     add file empty mode=0644 owner=root group=sys path=/etc/minor_perm preserve=true
3334                     add file empty mode=0644 owner=root group=sys path=/etc/security/device_policy preserve=true
3335                     add file empty mode=0644 owner=root group=sys path=/etc/security/extra_privs preserve=true
3336                     close
3337                 """
3338 
3339                 self.devlink10 = """
3340                     open devlinktest@1.0,5.11-0
3341                     add driver name=zerg devlink="type=ddi_pseudo;name=zerg\\t\D"
3342                     add driver name=borg devlink="type=ddi_pseudo;name=borg\\t\D" devlink="type=ddi_pseudo;name=warg\\t\D"
3343                     add depend type=require fmri=devicebase
3344                     close
3345                 """
3346 
3347                 self.devlink20 = """
3348                     open devlinktest@2.0,5.11-0
3349                     add driver name=zerg devlink="type=ddi_pseudo;name=zerg2\\t\D" devlink="type=ddi_pseudo;name=zorg\\t\D"
3350                     add driver name=borg devlink="type=ddi_pseudo;name=borg\\t\D" devlink="type=ddi_pseudo;name=zork\\t\D"
3351                     add depend type=require fmri=devicebase
3352                     close
3353                 """
3354 
3355                 self.devalias10 = """
3356                     open devalias@1,5.11
3357                     add driver name=zerg alias=pci8086,1234 alias=pci8086,4321
3358                     close
3359                 """
3360 
3361                 self.devalias20 = """
3362                     open devalias@2,5.11
3363                     add driver name=zerg alias=pci8086,5555
3364                     close
3365                 """
3366 
3367                 self.devaliasmove10 = """
3368                     open devaliasmove@1,5.11
3369                     add driver name=zerg alias=pci8086,5555
3370                     close
3371                 """
3372 
3373                 self.devaliasmove20 = """
3374                     open devaliasmove@2,5.11
3375                     add driver name=zerg
3376                     add driver name=borg alias=pci8086,5555
3377                     close
3378                 """
3379 
3380                 self.badhardlink1 = """
3381                     open badhardlink1@1.0,5.11-0
3382                     add hardlink path=foo target=bar
3383                     close
3384                 """
3385 
3386                 self.badhardlink2 = """
3387                     open badhardlink2@1.0,5.11-0
3388                     add file cat mode=0555 owner=root group=bin path=/etc/motd
3389                     add hardlink path=foo target=/etc/motd
3390                     close
3391                 """
3392 
3393                 self.make_misc_files(self.misc_files)
3394 
3395         def test_basics_0(self):
3396                 """Send basic infrastructure, install and uninstall."""
3397 
3398                 self.pkgsend_bulk(self.rurl, (self.basics0, self.basics1))
3399                 self.image_create(self.rurl)
3400 
3401                 self.pkg("list -a")
3402                 self.pkg("list", exit=1)
3403 
3404                 self.pkg("install basics")
3405                 self.pkg("install basics1")
3406 
3407                 self.pkg("list")
3408                 self.pkg("verify")
3409 
3410                 self.pkg("uninstall basics basics1")
3411                 self.pkg("verify")
3412 
3413         def test_grouptest(self):
3414 
3415                 self.pkgsend_bulk(self.rurl, (self.basics0, self.basics1,
3416                     self.grouptest))
3417                 self.image_create(self.rurl)
3418                 self.pkg("install basics")
3419                 self.pkg("install basics1")
3420 
3421                 self.pkg("install grouptest")
3422                 self.pkg("verify")
3423                 self.pkg("uninstall grouptest")
3424                 self.pkg("verify")
3425 
3426         def test_usertest(self):
3427 
3428                 self.pkgsend_bulk(self.rurl, (self.basics0, self.basics1,
3429                     self.grouptest, self.usertest10))
3430                 self.image_create(self.rurl)
3431                 self.pkg("install basics")
3432                 self.pkg("install basics1")
3433 
3434                 self.pkg("install usertest")
3435                 self.pkg("verify")
3436                 self.pkg("contents -m usertest")
3437 
3438                 self.pkgsend_bulk(self.rurl, self.usertest11)
3439                 self.pkg("refresh")
3440                 self.pkg("install usertest")
3441                 self.pkg("verify")
3442                 self.pkg("contents -m usertest")
3443 
3444                 self.pkg("uninstall usertest")
3445                 self.pkg("verify")
3446 
3447         def test_primordial_usergroup(self):
3448                 """Ensure that we can install user and group actions in the same
3449                 transaction as /etc/passwd, /etc/group, etc."""
3450 
3451                 self.pkgsend_bulk(self.rurl, [self.baseuser, self.singleuser])
3452 
3453                 self.image_create(self.rurl)
3454                 self.pkg("install system/action/user")
3455                 self.pkg("verify")
3456 
3457                 self.image_destroy()
3458                 self.image_create(self.rurl)
3459                 self.pkg("install singleuser", exit=1)
3460 
3461         def test_ftpuser(self):
3462                 """Make sure we correctly handle /etc/ftpd/ftpusers."""
3463 
3464                 notftpuser = """
3465                 open notftpuser@1
3466                 add user username=animal group=root ftpuser=false
3467                 close"""
3468 
3469                 ftpuserexp = """
3470                 open ftpuserexp@1
3471                 add user username=fozzie group=root ftpuser=true
3472                 close"""
3473 
3474                 ftpuserimp = """
3475                 open ftpuserimp@1
3476                 add user username=gonzo group=root
3477                 close"""
3478 
3479                 self.pkgsend_bulk(self.rurl, (self.basics0, notftpuser,
3480                     ftpuserexp, ftpuserimp))
3481                 self.image_create(self.rurl)
3482 
3483                 self.pkg("install basics")
3484 
3485                 # Add a user with ftpuser=false.  Make sure the user is added to
3486                 # the file, and that the user verifies.
3487                 self.pkg("install notftpuser")
3488                 fpath = self.get_img_path() + "/etc/ftpd/ftpusers"
3489                 self.assert_("animal\n" in file(fpath).readlines())
3490                 self.pkg("verify notftpuser")
3491 
3492                 # Add a user with an explicit ftpuser=true.  Make sure the user
3493                 # is not added to the file, and that the user verifies.
3494                 self.pkg("install ftpuserexp")
3495                 self.assert_("fozzie\n" not in file(fpath).readlines())
3496                 self.pkg("verify ftpuserexp")
3497 
3498                 # Add a user with an implicit ftpuser=true.  Make sure the user
3499                 # is not added to the file, and that the user verifies.
3500                 self.pkg("install ftpuserimp")
3501                 self.assert_("gonzo\n" not in file(fpath).readlines())
3502                 self.pkg("verify ftpuserimp")
3503 
3504                 # Put a user into the ftpusers file as shipped, then add that
3505                 # user, with ftpuser=false.  Make sure the user remains in the
3506                 # file, and that the user verifies.
3507                 self.pkg("uninstall notftpuser")
3508                 file(fpath, "a").write("animal\n")
3509                 self.pkg("install notftpuser")
3510                 self.assert_("animal\n" in file(fpath).readlines())
3511                 self.pkg("verify notftpuser")
3512 
3513                 # Put a user into the ftpusers file as shipped, then add that
3514                 # user, with an explicit ftpuser=true.  Make sure the user is
3515                 # stripped from the file, and that the user verifies.
3516                 self.pkg("uninstall ftpuserexp")
3517                 file(fpath, "a").write("fozzie\n")
3518                 self.pkg("install ftpuserexp")
3519                 self.assert_("fozzie\n" not in file(fpath).readlines())
3520                 self.pkg("verify ftpuserexp")
3521 
3522                 # Put a user into the ftpusers file as shipped, then add that
3523                 # user, with an implicit ftpuser=true.  Make sure the user is
3524                 # stripped from the file, and that the user verifies.
3525                 self.pkg("uninstall ftpuserimp")
3526                 file(fpath, "a").write("gonzo\n")
3527                 self.pkg("install ftpuserimp")
3528                 self.assert_("gonzo\n" not in file(fpath).readlines())
3529                 self.pkg("verify ftpuserimp")
3530 
3531         def test_groupverify(self):
3532                 """Make sure we correctly verify group actions when users have
3533                 been added."""
3534 
3535                 simplegroup = """
3536                 open simplegroup@1
3537                 add group groupname=muppets
3538                 close"""
3539 
3540                 self.pkgsend_bulk(self.rurl, (self.basics0, simplegroup))
3541                 self.image_create(self.rurl)
3542 
3543                 self.pkg("install basics")
3544                 self.pkg("install simplegroup")
3545                 self.pkg("verify simplegroup")
3546 
3547                 gpath = self.get_img_path() + "/etc/group"
3548                 gdata = file(gpath).readlines()
3549                 gdata[-1] = gdata[-1].rstrip() + "kermit,misspiggy\n"
3550                 file(gpath, "w").writelines(gdata)
3551                 self.pkg("verify simplegroup")
3552 
3553         def test_userverify(self):
3554                 """Make sure we correctly verify user actions when the on-disk
3555                 databases have been modified."""
3556 
3557                 simpleuser = """
3558                 open simpleuser@1
3559                 add user username=misspiggy group=root gcos-field="&amp; loves Kermie" login-shell=/bin/sh
3560                 close"""
3561 
3562                 self.pkgsend_bulk(self.rurl, (self.basics0, simpleuser))
3563                 self.image_create(self.rurl)
3564 
3565                 self.pkg("install basics")
3566                 self.pkg("install simpleuser")
3567                 self.pkg("verify simpleuser")
3568 
3569                 ppath = self.get_img_path() + "/etc/passwd"
3570                 pdata = file(ppath).readlines()
3571                 spath = self.get_img_path() + "/etc/shadow"
3572                 sdata = file(spath).readlines()
3573 
3574                 def finderr(err):
3575                         self.assert_("\t\t" + err in self.output)
3576 
3577                 # change a provided, empty-default field to something else
3578                 pdata[-1] = "misspiggy:x:5:0:&amp; loves Kermie:/:/bin/zsh"
3579                 file(ppath, "w").writelines(pdata)
3580                 self.pkg("verify simpleuser", exit=1)
3581                 finderr("login-shell: '/bin/zsh' should be '/bin/sh'")
3582                 self.pkg("fix simpleuser")
3583                 self.pkg("verify simpleuser")
3584 
3585                 # change a provided, non-empty-default field to the default
3586                 pdata[-1] = "misspiggy:x:5:0:&amp; User:/:/bin/sh"
3587                 file(ppath, "w").writelines(pdata)
3588                 self.pkg("verify simpleuser", exit=1)
3589                 finderr("gcos-field: '&amp; User' should be '&amp; loves Kermie'")
3590                 self.pkg("fix simpleuser")
3591                 self.pkg("verify simpleuser")
3592 
3593                 # change a non-provided, non-empty-default field to something
3594                 # other than the default
3595                 pdata[-1] = "misspiggy:x:5:0:&amp; loves Kermie:/misspiggy:/bin/sh"
3596                 file(ppath, "w").writelines(pdata)
3597                 self.pkg("verify simpleuser", exit=1)
3598                 finderr("home-dir: '/misspiggy' should be '/'")
3599                 self.pkg("fix simpleuser")
3600                 self.pkg("verify simpleuser")
3601 
3602                 # add a non-provided, empty-default field
3603                 pdata[-1] = "misspiggy:x:5:0:&amp; loves Kermie:/:/bin/sh"
3604                 sdata[-1] = "misspiggy:*LK*:14579:7:::::"
3605                 file(ppath, "w").writelines(pdata)
3606                 os.chmod(spath,
3607                     stat.S_IMODE(os.stat(spath).st_mode)|stat.S_IWUSR)
3608                 file(spath, "w").writelines(sdata)
3609                 self.pkg("verify simpleuser", exit=1)
3610                 finderr("min: '7' should be '&lt;empty&gt;'")
3611                 # fails fix since we don't repair shadow entries on purpose
3612                 self.pkg("fix simpleuser")
3613                 self.pkg("verify simpleuser", exit=1)
3614                 finderr("min: '7' should be '&lt;empty&gt;'")
3615 
3616                 # remove a non-provided, non-empty-default field
3617                 pdata[-1] = "misspiggy:x:5:0:&amp; loves Kermie::/bin/sh"
3618                 sdata[-1] = "misspiggy:*LK*:14579::::::"
3619                 file(ppath, "w").writelines(pdata)
3620                 file(spath, "w").writelines(sdata)
3621                 self.pkg("verify simpleuser", exit=1)
3622                 finderr("home-dir: '' should be '/'")
3623                 self.pkg("fix simpleuser")
3624                 self.pkg("verify simpleuser")
3625 
3626                 # remove a provided, non-empty-default field
3627                 pdata[-1] = "misspiggy:x:5:0::/:/bin/sh"
3628                 file(ppath, "w").writelines(pdata)
3629                 self.pkg("verify simpleuser", exit=1)
3630                 finderr("gcos-field: '' should be '&amp; loves Kermie'")
3631                 self.pkg("fix simpleuser")
3632                 self.pkg("verify simpleuser")
3633 
3634                 # remove a provided, empty-default field
3635                 pdata[-1] = "misspiggy:x:5:0:&amp; loves Kermie:/:"
3636                 file(ppath, "w").writelines(pdata)
3637                 self.pkg("verify simpleuser", exit=1)
3638                 finderr("login-shell: '' should be '/bin/sh'")
3639                 self.pkg("fix simpleuser")
3640                 self.pkg("verify simpleuser")
3641 
3642                 # remove the user from /etc/passwd
3643                 pdata[-1] = "misswiggy:x:5:0:&amp; loves Kermie:/:"
3644                 file(ppath, "w").writelines(pdata)
3645                 self.pkg("verify simpleuser", exit=1)
3646                 finderr("login-shell: '&lt;missing&gt;' should be '/bin/sh'")
3647                 finderr("gcos-field: '&lt;missing&gt;' should be '&amp; loves Kermie'")
3648                 finderr("group: '&lt;missing&gt;' should be 'root'")
3649                 self.pkg("fix simpleuser")
3650                 self.pkg("verify simpleuser")
3651 
3652                 # remove the user completely
3653                 pdata[-1] = "misswiggy:x:5:0:&amp; loves Kermie:/:"
3654                 sdata[-1] = "misswiggy:*LK*:14579::::::"
3655                 file(ppath, "w").writelines(pdata)
3656                 file(spath, "w").writelines(sdata)
3657                 self.pkg("verify simpleuser", exit=1)
3658                 finderr("username: '&lt;missing&gt;' should be 'misspiggy'")
3659                 self.pkg("fix simpleuser")
3660                 self.pkg("verify simpleuser")
3661 
3662 
3663         def test_minugid(self):
3664                 """Ensure that an unspecified uid/gid results in the first
3665                 unused."""
3666 
3667                 self.pkgsend_bulk(self.rurl, (self.basics0, self.ugidtest))
3668                 self.image_create(self.rurl)
3669 
3670                 # This will lay down the sample passwd file, group file, etc.
3671                 self.pkg("install basics")
3672 
3673                 self.pkg("install ugidtest")
3674                 passwd_file = file(os.path.join(self.get_img_path(),
3675                     "/etc/passwd"))
3676                 for line in passwd_file:
3677                         if line.startswith("dummy"):
3678                                 self.assert_(line.startswith("dummy:x:5:"))
3679                 passwd_file.close()
3680                 group_file = file(os.path.join(self.get_img_path(),
3681                     "/etc/group"))
3682                 for line in group_file:
3683                         if line.startswith("dummy"):
3684                                 self.assert_(line.startswith("dummy::5:"))
3685                 group_file.close()
3686 
3687         def test_upgrade_with_user(self):
3688                 """Ensure that we can add a user and change file ownership to
3689                 that user in the same delta (mysql tripped over this early on
3690                 in IPS development)."""
3691 
3692                 self.pkgsend_bulk(self.rurl, (self.basics0, self.basics1,
3693                     self.silver10, self.silver20, self.grouptest))
3694                 self.image_create(self.rurl)
3695                 self.pkg("install basics@1.0")
3696                 self.pkg("install basics1@1.0")
3697                 self.pkg("install silver@1.0")
3698                 self.pkg("list silver@1.0")
3699                 self.pkg("verify -v")
3700                 self.pkg("install silver@2.0")
3701                 self.pkg("verify -v")
3702 
3703         def test_upgrade_garbage_passwd(self):
3704                 self.pkgsend_bulk(self.rurl, (self.basics0, self.singleuser))
3705                 self.image_create(self.rurl)
3706                 pwd_path = os.path.join(self.get_img_path(), "etc/passwd")
3707 
3708                 # Put a garbage line in /etc/passwd, and make sure we can
3709                 # install a user, uninstall the user, and preserve the garbage
3710                 # line.  Once with a blank line in the middle, once with a
3711                 # non-blank line with too few fields, once with a non-blank line
3712                 # with too many fields, and once with a blank line at the end.
3713                 for lineno, garbage in ((3, ""), (3, "garbage"),
3714                     (3, ":::::::::"), (100, "")):
3715                         garbage += "\n"
3716                         self.pkg("install basics")
3717                         with file(pwd_path, "r+") as pwd_file:
3718                                 lines = pwd_file.readlines()
3719                                 lines[lineno:lineno] = garbage
3720                                 pwd_file.truncate(0)
3721                                 pwd_file.seek(0)
3722                                 pwd_file.writelines(lines)
3723                         self.pkg("install singleuser")
3724                         with file(pwd_path) as pwd_file:
3725                                 lines = pwd_file.readlines()
3726                                 self.assert_(garbage in lines)
3727                         self.pkg("uninstall singleuser")
3728                         with file(pwd_path) as pwd_file:
3729                                 lines = pwd_file.readlines()
3730                                 self.assert_(garbage in lines)
3731 
3732                         self.pkg("uninstall '*'")
3733 
3734         def test_user_in_grouplist(self):
3735                 """If a user is present in a secondary group list when the user
3736                 is installed, the client shouldn't crash."""
3737 
3738                 self.pkgsend_bulk(self.rurl, (self.basics0, self.only_user10))
3739                 self.image_create(self.rurl)
3740                 self.pkg("install basics@1.0")
3741                 group_path = os.path.join(self.get_img_path(), "etc/group")
3742                 with file(group_path, "r+") as group_file:
3743                         lines = group_file.readlines()
3744                         lines[0] = lines[0][:-1] + "Kermit" + "\n"
3745                         group_file.truncate(0)
3746                         group_file.seek(0)
3747                         group_file.writelines(lines)
3748                 self.pkg("install only_user@1.0")
3749 
3750         def test_invalid_open(self):
3751                 """Send invalid package definitions (invalid fmris); expect
3752                 failure."""
3753 
3754                 for char in self.pkg_name_valid_chars["never"]:
3755                         invalid_name = "invalid%spkg@1.0,5.11-0" % char
3756                         self.pkgsend(self.rurl, "open '%s'" % invalid_name,
3757                             exit=1)
3758 
3759                 for char in self.pkg_name_valid_chars["after-first"]:
3760                         invalid_name = "%sinvalidpkg@1.0,5.11-0" % char
3761                         if char == "-":
3762                                 cmd = "open -- '%s'" % invalid_name
3763                         else:
3764                                 cmd = "open '%s'" % invalid_name
3765                         self.pkgsend(self.rurl, cmd, exit=1)
3766 
3767                         invalid_name = "invalid/%spkg@1.0,5.11-0" % char
3768                         cmd = "open '%s'" % invalid_name
3769                         self.pkgsend(self.rurl, cmd, exit=1)
3770 
3771         def test_valid_open(self):
3772                 """Send a series of valid packages; expect success."""
3773 
3774                 for char in self.pkg_name_valid_chars["always"]:
3775                         valid_name = "%svalid%s/%spkg%s@1.0,5.11-0" % (char,
3776                             char, char, char)
3777                         self.pkgsend(self.rurl, "open '%s'" % valid_name)
3778                         self.pkgsend(self.rurl, "close -A")
3779 
3780                 for char in self.pkg_name_valid_chars["after-first"]:
3781                         valid_name = "v%salid%spkg@1.0,5.11-0" % (char, char)
3782                         self.pkgsend(self.rurl, "open '%s'" % valid_name)
3783                         self.pkgsend(self.rurl, "close -A")
3784 
3785                 for char in self.pkg_name_valid_chars["at-end"]:
3786                         valid_name = "validpkg%s@1.0,5.11-0" % char
3787                         self.pkgsend(self.rurl, "open '%s'" % valid_name)
3788                         self.pkgsend(self.rurl, "close -A")
3789 
3790         def test_devlink(self):
3791                 # driver actions are not valid except on OpenSolaris
3792                 if portable.util.get_canonical_os_name() != "sunos":
3793                         return
3794 
3795                 self.pkgsend_bulk(self.rurl, (self.devicebase, self.devlink10,
3796                     self.devlink20))
3797                 self.image_create(self.rurl)
3798 
3799                 def readfile():
3800                         dlf = file(os.path.join(self.get_img_path(),
3801                             "etc/devlink.tab"))
3802                         dllines = dlf.readlines()
3803                         dlf.close()
3804                         return dllines
3805 
3806                 def writefile(dllines):
3807                         dlf = file(os.path.join(self.get_img_path(),
3808                             "etc/devlink.tab"), "w")
3809                         dlf.writelines(dllines)
3810                         dlf.close()
3811 
3812                 def assertContents(dllines, contents):
3813                         actual = re.findall("name=([^\t;]*)",
3814                             "\n".join(dllines), re.M)
3815                         self.assert_(set(actual) == set(contents))
3816 
3817                 # Install
3818                 self.pkg("install devlinktest@1.0")
3819                 self.pkg("verify -v")
3820 
3821                 dllines = readfile()
3822 
3823                 # Verify that three entries got added
3824                 self.assert_(len(dllines) == 3)
3825 
3826                 # Verify that the tab character got written correctly
3827                 self.assert_(dllines[0].find("\t") &gt; 0)
3828 
3829                 # Upgrade
3830                 self.pkg("install devlinktest@2.0")
3831                 self.pkg("verify -v")
3832 
3833                 dllines = readfile()
3834 
3835                 # Verify that there are four entries now
3836                 self.assert_(len(dllines) == 4)
3837 
3838                 # Verify they are what they should be
3839                 assertContents(dllines, ["zerg2", "zorg", "borg", "zork"])
3840 
3841                 # Remove
3842                 self.pkg("uninstall devlinktest")
3843                 self.pkg("verify -v")
3844 
3845                 # Install again
3846                 self.pkg("install devlinktest@1.0")
3847 
3848                 # Diddle with it
3849                 dllines = readfile()
3850                 for i, line in enumerate(dllines):
3851                         if line.find("zerg") != -1:
3852                                 dllines[i] = "type=ddi_pseudo;name=zippy\t\D\n"
3853                 writefile(dllines)
3854 
3855                 # Upgrade
3856                 self.pkg("install devlinktest@2.0")
3857 
3858                 # Verify that we spewed a message on upgrade
3859                 self.assert_(self.output.find("not found") != -1)
3860                 self.assert_(self.output.find("name=zerg") != -1)
3861 
3862                 # Verify the new set
3863                 dllines = readfile()
3864                 self.assert_(len(dllines) == 5)
3865                 assertContents(dllines,
3866                     ["zerg2", "zorg", "borg", "zork", "zippy"])
3867 
3868                 self.pkg("uninstall devlinktest")
3869 
3870                 # Null out the "zippy" entry
3871                 writefile([])
3872 
3873                 # Install again
3874                 self.pkg("install devlinktest@1.0")
3875 
3876                 # Diddle with it
3877                 dllines = readfile()
3878                 for i, line in enumerate(dllines):
3879                         if line.find("zerg") != -1:
3880                                 dllines[i] = "type=ddi_pseudo;name=zippy\t\D\n"
3881                 writefile(dllines)
3882 
3883                 # Remove
3884                 self.pkg("uninstall devlinktest")
3885 
3886                 # Verify that we spewed a message on removal
3887                 self.assert_(self.output.find("not found") != -1)
3888                 self.assert_(self.output.find("name=zerg") != -1)
3889 
3890                 # Verify that the one left behind was the one we overwrote.
3891                 dllines = readfile()
3892                 self.assert_(len(dllines) == 1)
3893                 assertContents(dllines, ["zippy"])
3894 
3895                 # Null out the "zippy" entry, but add the "zerg" entry
3896                 writefile(["type=ddi_pseudo;name=zerg\t\D\n"])
3897 
3898                 # Install ... again
3899                 self.pkg("install devlinktest@1.0")
3900 
3901                 # Make sure we didn't get a second zerg line
3902                 dllines = readfile()
3903                 self.failUnless(len(dllines) == 3, msg=dllines)
3904                 assertContents(dllines, ["zerg", "borg", "warg"])
3905 
3906                 # Now for the same test on upgrade
3907                 dllines.append("type=ddi_pseudo;name=zorg\t\D\n")
3908                 writefile(dllines)
3909 
3910                 self.pkg("install devlinktest@2.0")
3911                 dllines = readfile()
3912                 self.failUnless(len(dllines) == 4, msg=dllines)
3913                 assertContents(dllines, ["zerg2", "zorg", "borg", "zork"])
3914 
3915         def test_driver_aliases_upgrade(self):
3916                 """Make sure that aliases properly appear and disappear on
3917                 upgrade.  This is the result of a bug in update_drv, but it's
3918                 not a bad idea to test some of this ourselves."""
3919 
3920                 # driver actions are not valid except on OpenSolaris
3921                 if portable.util.get_canonical_os_name() != "sunos":
3922                         return
3923 
3924                 self.pkgsend_bulk(self.rurl, [self.devicebase, self.devalias10,
3925                     self.devalias20])
3926 
3927                 self.image_create(self.rurl)
3928                 self.pkg("install devicebase devalias@1")
3929                 self.pkg("update devalias")
3930                 self.pkg("verify devalias")
3931 
3932                 daf = open(os.path.join(self.get_img_path(),
3933                     "etc/driver_aliases"))
3934                 dalines = daf.readlines()
3935                 daf.close()
3936 
3937                 self.assert_(len(dalines) == 1, msg=dalines)
3938                 self.assert_(",1234" not in dalines[0])
3939                 self.assert_(",4321" not in dalines[0])
3940                 self.assert_(",5555" in dalines[0])
3941 
3942         def test_driver_aliases_move(self):
3943                 """Make sure that an alias can be moved from one driver action
3944                 to another."""
3945 
3946                 self.pkgsend_bulk(self.rurl, [self.devicebase,
3947                     self.devaliasmove10, self.devaliasmove20])
3948 
3949                 self.image_create(self.rurl)
3950                 self.pkg("install devicebase devaliasmove@1")
3951                 self.pkg("update devaliasmove")
3952                 self.assert_("pci8086,5555" not in self.output)
3953 
3954         def test_uninstall_without_perms(self):
3955                 """Test for bug 4569"""
3956 
3957                 pkg_list = [self.foo10, self.only_attr10, self.only_depend10,
3958                     self.only_directory10, self.only_file10,
3959                     self.only_group10, self.only_hardlink10, self.only_legacy10,
3960                     self.only_license10, self.only_link10, self.only_user10]
3961 
3962                 # driver actions are not valid except on OpenSolaris
3963                 if portable.util.get_canonical_os_name() == 'sunos':
3964                         pkg_list += [self.only_driver10]
3965 
3966                 self.pkgsend_bulk(self.rurl, pkg_list + [
3967                     self.devicebase + self.basics0 + self.basics1])
3968 
3969                 self.image_create(self.rurl)
3970 
3971                 name_pat = re.compile("^\s+open\s+(\S+)\@.*$")
3972 
3973                 def __manually_check_deps(name, install=True, exit=0):
3974                         cmd = "install --no-refresh"
3975                         if not install:
3976                                 cmd = "uninstall"
3977                         if name == "only_depend" and not install:
3978                                 self.pkg("uninstall foo", exit=exit)
3979                         elif name == "only_driver":
3980                                 self.pkg("%s devicebase" % cmd, exit=exit)
3981                         elif name == "only_group":
3982                                 self.pkg("%s basics" % cmd, exit=exit)
3983                         elif name == "only_hardlink":
3984                                 self.pkg("%s only_file" % cmd, exit=exit)
3985                         elif name == "only_user":
3986                                 if install:
3987                                         self.pkg("%s basics" % cmd, exit=exit)
3988                                         self.pkg("%s only_group" % cmd, exit=exit)
3989                                 else:
3990                                         self.pkg("%s only_group" % cmd, exit=exit)
3991                                         self.pkg("%s basics" % cmd, exit=exit)
3992                 for p in pkg_list:
3993                         name_mat = name_pat.match(p.splitlines()[1])
3994                         pname = name_mat.group(1)
3995                         __manually_check_deps(pname, exit=[0, 4])
3996                         self.pkg("install --no-refresh %s" % pname,
3997                             su_wrap=True, exit=1)
3998                         self.pkg("install %s" % pname, su_wrap=True,
3999                             exit=1)
4000                         self.pkg("install --no-refresh %s" % pname)
4001                         self.pkg("uninstall %s" % pname, su_wrap=True,
4002                             exit=1)
4003                         self.pkg("uninstall %s" % pname)
4004                         __manually_check_deps(pname, install=False)
4005 
4006                 for p in pkg_list:
4007                         name_mat = name_pat.match(p.splitlines()[1])
4008                         pname = name_mat.group(1)
4009                         __manually_check_deps(pname, exit=[0, 4])
4010                         self.pkg("install --no-refresh %s" % pname)
4011 
4012                 for p in pkg_list:
4013                         self.pkgsend_bulk(self.rurl, p)
4014                 self.pkgsend_bulk(self.rurl, (self.devicebase, self.basics0,
4015                     self.basics1))
4016 
4017                 # Modifying operations require permissions needed to create and
4018                 # manage lock files.
4019                 self.pkg("update --no-refresh", su_wrap=True, exit=1)
4020 
4021                 self.pkg("refresh")
4022                 self.pkg("update", su_wrap=True, exit=1)
4023                 # Should fail since user doesn't have permission to refresh
4024                 # publisher metadata.
4025                 self.pkg("refresh --full", su_wrap=True, exit=1)
4026                 self.pkg("refresh --full")
4027                 self.pkg("update --no-refresh", su_wrap=True,
4028                     exit=1)
4029                 self.pkg("update")
4030 
4031         def test_bug_3222(self):
4032                 """ Verify that a timestamp of '0' for a passwd file will not
4033                     cause further package operations to fail.  This can happen
4034                     when there are time synchronization issues within a virtual
4035                     environment or in other cases. """
4036 
4037                 self.pkgsend_bulk(self.rurl, (self.basics0, self.only_user10,
4038                     self.only_user_file10, self.only_group10,
4039                     self.only_group_file10, self.grouptest, self.usertest10))
4040                 self.image_create(self.rurl)
4041                 fname = os.path.join(self.get_img_path(), "etc", "passwd")
4042                 self.pkg("install basics")
4043 
4044                 # This should work regardless of whether a user is installed
4045                 # at the same time as the file in a package, or if the user is
4046                 # installed first and then files owned by that user are
4047                 # installed.
4048                 plists = [["grouptest", "usertest"],
4049                     ["only_user", "only_user_file"],
4050                     ["only_group", "only_group_file"]]
4051                 for plist in plists:
4052                         for pname in plist:
4053                                 os.utime(fname, (0, 0))
4054                                 self.pkg("install %s" % pname)
4055                                 self.pkg("verify")
4056 
4057                         for pname in reversed(plist):
4058                                 os.utime(fname, (0, 0))
4059                                 self.pkg("uninstall %s" % pname)
4060                                 self.pkg("verify")
4061 
4062         def test_bad_hardlinks(self):
4063                 """A couple of bogus hard link target tests."""
4064 
4065                 self.pkgsend_bulk(self.rurl, (self.badhardlink1,
4066                     self.badhardlink2))
4067                 self.image_create(self.rurl)
4068 
4069                 # A package which tries to install a hard link to a target that
4070                 # doesn't exist shouldn't stack trace, but exit sanely.
4071                 self.pkg("install badhardlink1", exit=1)
4072 
4073                 # A package which tries to install a hard link to a target
4074                 # specified as an absolute path should install that link
4075                 # relative to the image root.
4076                 self.pkg("install badhardlink2")
4077                 ino1 = os.stat(os.path.join(self.get_img_path(), "foo")).st_ino
4078                 ino2 = os.stat(os.path.join(self.get_img_path(), "etc/motd")).st_ino
4079                 self.assert_(ino1 == ino2)
4080 
4081         def test_legacy(self):
4082                 self.pkgsend_bulk(self.rurl,
4083                     (self.csu1, self.csu1_2, self.csu2, self.csu2_2,
4084                     self.csu3, self.csu3_2))
4085                 self.image_create(self.rurl)
4086 
4087                 self.pkg("install csu1@1 csu2@1 csu3@1")
4088 
4089                 # Make sure we installed one and only one pkginfo file, and with
4090                 # the correct information.
4091                 vsp = self.get_img_file_path("var/sadm/pkg")
4092                 pi = os.path.join(vsp, "SUNWcsu/pkginfo")
4093                 pi2 = os.path.join(vsp, "SUNWcsu/pkginfo.2")
4094                 pi3 = os.path.join(vsp, "SUNWcsu/pkginfo.3")
4095                 self.assert_(os.path.exists(pi), "pkginfo doesn't exist")
4096                 self.file_contains(pi, "VERSION=11.11,REV=2009.11.11")
4097                 self.assert_(not os.path.exists(pi2), "pkginfo.2 exists")
4098                 self.assert_(not os.path.exists(pi3), "pkginfo.3 exists")
4099                 # Create the hardlinks as we'd have for the old refcounting
4100                 # system.
4101                 os.link(pi, pi2)
4102                 os.link(pi, pi3)
4103 
4104                 # Make sure that upgrading the actions modifies the pkginfo file
4105                 # correctly, and that the hardlinks go away.
4106                 self.pkg("update")
4107                 self.file_contains(pi, "VERSION=11.11,REV=2010.11.11")
4108                 self.assert_(not os.path.exists(pi2), "pkginfo.2 exists")
4109                 self.assert_(not os.path.exists(pi3), "pkginfo.3 exists")
4110 
4111                 # Start over, but this time "break" the hardlinks.
4112                 self.pkg("uninstall -vvv \*")
4113                 self.pkg("install csu1@1 csu2@1 csu3@1")
4114                 shutil.copy(pi, pi2)
4115                 shutil.copy(pi, pi3)
4116                 self.pkg("update")
4117                 self.file_contains(pi, "VERSION=11.11,REV=2010.11.11")
4118                 self.assert_(not os.path.exists(pi2), "pkginfo.2 exists")
4119                 self.assert_(not os.path.exists(pi3), "pkginfo.3 exists")
4120 
4121 
4122 class TestDependencies(pkg5unittest.SingleDepotTestCase):
4123         # Only start/stop the depot once (instead of for every test)
4124         persistent_setup = True
4125 
4126         pkg10 = """
4127             open pkg1@1.0,5.11-0
4128             add depend type=optional fmri=pkg:/pkg2
4129             close
4130         """
4131 
4132         pkg20 = """
4133             open pkg2@1.0,5.11-0
4134             close
4135         """
4136 
4137         pkg11 = """
4138             open pkg1@1.1,5.11-0
4139             add depend type=optional fmri=pkg:/pkg2@1.1
4140             close
4141         """
4142 
4143         pkg21 = """
4144             open pkg2@1.1,5.11-0
4145             close
4146         """
4147 
4148         pkg30 = """
4149             open pkg3@1.0,5.11-0
4150             add depend type=require fmri=pkg:/pkg1@1.1
4151             close
4152         """
4153 
4154         pkg40 = """
4155             open pkg4@1.0,5.11-0
4156             add depend type=exclude fmri=pkg:/pkg1@1.1
4157             close
4158         """
4159 
4160         pkg50 = """
4161             open pkg5@1.0,5.11-0
4162             add depend type=exclude fmri=pkg:/pkg1@1.1
4163             add depend type=require fmri=pkg:/pkg1@1.0
4164             close
4165         """
4166 
4167         pkg505 = """
4168             open pkg5@1.0.5,5.11-0
4169             add depend type=exclude fmri=pkg:/pkg1@1.1
4170             add depend type=require fmri=pkg:/pkg1@1.0
4171             close
4172         """
4173         pkg51 = """
4174             open pkg5@1.1,5.11-0
4175             add depend type=exclude fmri=pkg:/pkg1@1.1
4176             add depend type=exclude fmri=pkg:/pkg2
4177             add depend type=require fmri=pkg:/pkg1@1.0
4178             close
4179         """
4180         pkg60 = """
4181             open pkg6@1.0,5.11-0
4182             add depend type=exclude fmri=pkg:/pkg1@1.1
4183             close
4184         """
4185 
4186         pkg61 = """
4187             open pkg6@1.1,5.11-0
4188             close
4189         """
4190 
4191         bug_18653 = """
4192             open entire@1.0,5.11-0
4193             add depend type=incorporate fmri=osnet-incorporation@1.0
4194             close
4195             open entire@1.1,5.11-0
4196             add depend type=incorporate fmri=osnet-incorporation@1.1
4197             close
4198             open osnet-incorporation@1.0,5.11-0
4199             add depend type=incorporate fmri=sun-solaris@1.0
4200             add depend type=incorporate fmri=sun-solaris-510@1.0
4201             close
4202             open osnet-incorporation@1.1,5.11-0
4203             add depend type=incorporate fmri=sun-solaris@1.1
4204             add depend type=incorporate fmri=sun-solaris-510@1.1
4205             close
4206             open sun-solaris@1.0,5.11-0
4207             add depend type=require fmri=osnet-incorporation
4208             add depend type=conditional predicate=perl-510 fmri=sun-solaris-510@1.0
4209             close
4210             open sun-solaris@1.1,5.11-0
4211             add depend type=require fmri=osnet-incorporation
4212             add depend type=conditional predicate=perl-510 fmri=sun-solaris-510@1.1
4213             close
4214             open sun-solaris-510@1.0,5.11-0
4215             add depend type=require fmri=osnet-incorporation
4216             add depend type=require fmri=perl-510@1.0
4217             close
4218             open perl-510@1.0,5.11-0
4219             close
4220             open perl-510@1.1,5.11-0
4221             close
4222         """
4223 
4224         pkg70 = """
4225             open pkg7@1.0,5.11-0
4226             add depend type=conditional predicate=pkg:/pkg2@1.1 fmri=pkg:/pkg6@1.1
4227             close
4228         """
4229 
4230         pkg80 = """
4231             open pkg8@1.0,5.11-0
4232             add depend type=require-any fmri=pkg:/pkg9@1.0 fmri=pkg:/pkg2@1.1 fmri=pkg:/nonsuch
4233             close
4234         """
4235 
4236         pkg81 = """
4237             open pkg8@1.1,5.11-0
4238             add depend type=require-any fmri=pkg:/pkg9@1.1 fmri=pkg:/pkg2@1.1 fmri=pkg:/nonsuch
4239             close
4240         """
4241 
4242         pkg90 = """
4243             open pkg9@1.0,5.11-0
4244             close
4245         """
4246 
4247         pkg91 = """
4248             open pkg9@1.1,5.11-0
4249             close
4250         """
4251 
4252         pkg100 = """
4253             open pkg10@1.0,5.11-0
4254             close
4255         """
4256 
4257         pkg101 = """
4258             open pkg10@1.1,5.11-0
4259             close
4260         """
4261 
4262         pkg102 = """
4263             open pkg10@1.2,5.11-0
4264             add depend type=origin fmri=pkg10@1.1,5.11-0
4265             close
4266         """
4267 
4268         pkg110 = """
4269             open pkg11@1.0,5.11-0
4270             add depend type=origin root-image=true fmri=SUNWcs@0.5.11-0.75
4271             close
4272         """
4273         pkg111 = """
4274             open pkg11@1.1,5.11-0
4275             add depend type=origin root-image=true fmri=SUNWcs@0.5.11-1.0
4276             close
4277         """
4278 
4279         pkg121 = """
4280             open pkg12@1.1,5.11-0
4281         """
4282         pkg121 += "add depend type=parent fmri=%s" % \
4283             pkg.actions.depend.DEPEND_SELF
4284         pkg121 += """
4285             close
4286         """
4287 
4288         pkg122 = """
4289             open pkg12@1.2,5.11-0
4290         """
4291         pkg122 += "add depend type=parent fmri=%s" % \
4292             pkg.actions.depend.DEPEND_SELF
4293         pkg122 += """
4294             close
4295         """
4296 
4297         pkg123 = """
4298             open pkg12@1.3,5.11-0
4299         """
4300         pkg123 += "add depend type=parent fmri=%s" % \
4301             pkg.actions.depend.DEPEND_SELF
4302         pkg123 += """
4303             close
4304         """
4305 
4306         pkg132 = """
4307             open pkg13@1.2,5.11-0
4308             add depend type=parent fmri=pkg12@1.2,5.11-0
4309             close
4310         """
4311 
4312         pkg142 = """
4313             open pkg14@1.2,5.11-0
4314             add depend type=parent fmri=pkg12@1.2,5.11-0
4315             add depend type=parent fmri=pkg13@1.2,5.11-0
4316             close
4317         """
4318 
4319         pkg_nosol = """
4320             open pkg-nosol-A@1.0,5.11-0
4321             add depend type=require-any fmri=pkg:/pkg-nosol-B fmri=pkg:/pkg-nosol-C
4322             add depend type=require fmri=pkg:/pkg-nosol-D
4323             close
4324             open pkg-nosol-B@1.0,5.11-0
4325             add depend type=incorporate fmri=pkg:/pkg-nosol-E@2.0
4326             close
4327             open pkg-nosol-C@1.0,5.11-0
4328             add depend type=incorporate fmri=pkg:/pkg-nosol-E@2.0
4329             close
4330             open pkg-nosol-D@1.0,5.11-0
4331             add depend type=incorporate fmri=pkg:/pkg-nosol-E@1.0
4332             close
4333             open pkg-nosol-E@1.0,5.11-0
4334             close
4335             open pkg-nosol-E@2.0,5.11-0
4336             close
4337         """
4338 
4339         pkg_renames = """
4340             open pkg_need_rename@1.0,5.11-0
4341             add depend type=require fmri=pkg_rename
4342             close
4343             open pkg_rename@1.0,5.11-0
4344             add set name=pkg.renamed value=true
4345             add depend type=require fmri=pkg:/pkg_bar
4346             close
4347             open pkg_bar@1.0,5.11-0
4348             close
4349             open trusted@1.0,5.11-0
4350             add set name=pkg.renamed value=true
4351             add depend type=require fmri=system/trusted@1.0
4352             close
4353             open system/trusted@1.0,5.11-0
4354             close
4355         """
4356 
4357         pkgSUNWcs075 = """
4358             open SUNWcs@0.5.11-0.75
4359             close
4360         """
4361 
4362         leaf_template = """
4363             open pkg%s%s@%s,5.11-0
4364             add depend type=require fmri=pkg:/%s_incorp%s
4365             close
4366         """
4367         install_hold = "add set name=pkg.depend.install-hold value=test"
4368 
4369         leaf_expansion = [
4370                 ("A","_0", "1.0", "A", ""),
4371                 ("A","_1", "1.0", "A", ""),
4372                 ("A","_2", "1.0", "A", ""),
4373                 ("A","_3", "1.0", "A", ""),
4374 
4375                 ("B","_0", "1.0", "B", ""),
4376                 ("B","_1", "1.0", "B", ""),
4377                 ("B","_2", "1.0", "B", ""),
4378                 ("B","_3", "1.0", "B", ""),
4379 
4380                 ("A","_0", "1.1", "A", "@1.1"),
4381                 ("A","_1", "1.1", "A", "@1.1"),
4382                 ("A","_2", "1.1", "A", "@1.1"),
4383                 ("A","_3", "1.1", "A", "@1.1"),
4384 
4385                 ("B","_0", "1.1", "B", "@1.1"),
4386                 ("B","_1", "1.1", "B", "@1.1"),
4387                 ("B","_2", "1.1", "B", "@1.1"),
4388                 ("B","_3", "1.1", "B", "@1.1"),
4389 
4390                 ("A","_0", "1.2", "A", "@1.2"),
4391                 ("A","_1", "1.2", "A", "@1.2"),
4392                 ("A","_2", "1.2", "A", "@1.2"),
4393                 ("A","_3", "1.2", "A", "@1.2"),
4394 
4395                 ("B","_0", "1.2", "B", "@1.2"),
4396                 ("B","_1", "1.2", "B", "@1.2"),
4397                 ("B","_2", "1.2", "B", "@1.2"),
4398                 ("B","_3", "1.2", "B", "@1.2"),
4399 
4400                 ("A","_0", "1.3", "A", ""),
4401                 ("A","_1", "1.3", "A", ""),
4402                 ("A","_2", "1.3", "A", ""),
4403                 ("A","_3", "1.3", "A", ""),
4404 
4405                 ("B","_0", "1.3", "B", ""),
4406                 ("B","_1", "1.3", "B", ""),
4407                 ("B","_2", "1.3", "B", ""),
4408                 ("B","_3", "1.3", "B", "")
4409                 ]
4410 
4411         incorps = [ """
4412             open A_incorp@1.0,5.11-0
4413             add depend type=incorporate fmri=pkg:/pkgA_0@1.0
4414             add depend type=incorporate fmri=pkg:/pkgA_1@1.0
4415             add depend type=incorporate fmri=pkg:/pkgA_2@1.0
4416             add depend type=incorporate fmri=pkg:/pkgA_3@1.0
4417             close
4418         """,
4419 
4420         """
4421             open B_incorp@1.0,5.11-0
4422             add depend type=incorporate fmri=pkg:/pkgB_0@1.0
4423             add depend type=incorporate fmri=pkg:/pkgB_1@1.0
4424             add depend type=incorporate fmri=pkg:/pkgB_2@1.0
4425             add depend type=incorporate fmri=pkg:/pkgB_3@1.0
4426             close
4427         """,
4428 
4429         """
4430             open A_incorp@1.1,5.11-0
4431             add depend type=incorporate fmri=pkg:/pkgA_0@1.1
4432             add depend type=incorporate fmri=pkg:/pkgA_1@1.1
4433             add depend type=incorporate fmri=pkg:/pkgA_2@1.1
4434             add depend type=incorporate fmri=pkg:/pkgA_3@1.1
4435             add set name=pkg.depend.install-hold value=test
4436             close
4437         """,
4438 
4439         """
4440             open B_incorp@1.1,5.11-0
4441             add depend type=incorporate fmri=pkg:/pkgB_0@1.1
4442             add depend type=incorporate fmri=pkg:/pkgB_1@1.1
4443             add depend type=incorporate fmri=pkg:/pkgB_2@1.1
4444             add depend type=incorporate fmri=pkg:/pkgB_3@1.1
4445             add set name=pkg.depend.install-hold value=test
4446             close
4447         """,
4448 
4449         """
4450             open A_incorp@1.2,5.11-0
4451             add depend type=incorporate fmri=pkg:/pkgA_0@1.2
4452             add depend type=incorporate fmri=pkg:/pkgA_1@1.2
4453             add depend type=incorporate fmri=pkg:/pkgA_2@1.2
4454             add depend type=incorporate fmri=pkg:/pkgA_3@1.2
4455             add set name=pkg.depend.install-hold value=test.A
4456             close
4457         """,
4458 
4459         """
4460             open B_incorp@1.2,5.11-0
4461             add depend type=incorporate fmri=pkg:/pkgB_0@1.2
4462             add depend type=incorporate fmri=pkg:/pkgB_1@1.2
4463             add depend type=incorporate fmri=pkg:/pkgB_2@1.2
4464             add depend type=incorporate fmri=pkg:/pkgB_3@1.2
4465             add set name=pkg.depend.install-hold value=test.B
4466             close
4467         """,
4468 
4469         """
4470             open A_incorp@1.3,5.11-0
4471             add depend type=incorporate fmri=pkg:/pkgA_0@1.3
4472             add depend type=incorporate fmri=pkg:/pkgA_1@1.3
4473             add depend type=incorporate fmri=pkg:/pkgA_2@1.3
4474             add depend type=incorporate fmri=pkg:/pkgA_3@1.3
4475             add set name=pkg.depend.install-hold value=test.A
4476             close
4477         """,
4478 
4479         """
4480             open B_incorp@1.3,5.11-0
4481             add depend type=incorporate fmri=pkg:/pkgB_0@1.3
4482             add depend type=incorporate fmri=pkg:/pkgB_1@1.3
4483             add depend type=incorporate fmri=pkg:/pkgB_2@1.3
4484             add depend type=incorporate fmri=pkg:/pkgB_3@1.3
4485             add set name=pkg.depend.install-hold value=test.B
4486             close
4487         """,
4488 
4489         """
4490             open incorp@1.0,5.11-0
4491             add depend type=incorporate fmri=pkg:/A_incorp@1.0
4492             add depend type=incorporate fmri=pkg:/B_incorp@1.0
4493             add set name=pkg.depend.install-hold value=test
4494             close
4495         """,
4496 
4497         """
4498             open incorp@1.1,5.11-0
4499             add depend type=incorporate fmri=pkg:/A_incorp@1.1
4500             add depend type=incorporate fmri=pkg:/B_incorp@1.1
4501             add set name=pkg.depend.install-hold value=test
4502             close
4503         """,
4504 
4505         """
4506             open incorp@1.2,5.11-0
4507             add depend type=incorporate fmri=pkg:/A_incorp@1.2
4508             add depend type=incorporate fmri=pkg:/B_incorp@1.2
4509             add set name=pkg.depend.install-hold value=test
4510             close
4511         """,
4512         """
4513             open incorp@1.3,5.11-0
4514             add depend type=incorporate fmri=pkg:/A_incorp@1.3
4515             add depend type=exclude fmri=pkg:/pkgB_0
4516             add set name=pkg.depend.install-hold value=test
4517             close
4518         """
4519         ]
4520 
4521         bug_7394_incorp = """
4522             open bug_7394_incorp@1.0,5.11-0
4523             add depend type=incorporate fmri=pkg:/pkg1@2.0
4524             close
4525         """
4526 
4527         def setUp(self):
4528                 pkg5unittest.SingleDepotTestCase.setUp(self, image_count=2)
4529                 self.pkgsend_bulk(self.rurl, (self.pkg10, self.pkg20,
4530                     self.pkg11, self.pkg21, self.pkg30, self.pkg40, self.pkg50,
4531                     self.pkg505, self.pkg51, self.pkg60, self.pkg61,
4532                     self.bug_18653, self.pkg70, self.pkg80, self.pkg81,
4533                     self.pkg90, self.pkg91, self.bug_7394_incorp,
4534                     self.pkg100, self.pkg101, self.pkg102,
4535                     self.pkg110, self.pkg111,
4536                     self.pkg121, self.pkg122, self.pkg123, self.pkg132,
4537                     self.pkg142, self.pkg_nosol, self.pkg_renames,
4538                     self.pkgSUNWcs075))
4539 
4540                 self.leaf_pkgs = []
4541                 for t in self.leaf_expansion:
4542                         self.leaf_pkgs.extend(self.pkgsend_bulk(self.rurl,
4543                             self.leaf_template % t))
4544 
4545                 self.incorp_pkgs = []
4546                 for i in self.incorps:
4547                         self.incorp_pkgs.extend(self.pkgsend_bulk(self.rurl, i))
4548 
4549         def test_rename_matching(self):
4550                 """Verify install won't fail with a multiple match error for
4551                 a renamed package that shares a common basename."""
4552 
4553                 self.image_create(self.rurl)
4554                 self.pkg("install trusted")
4555                 self.pkg("info system/trusted")
4556 
4557         def test_require_dependencies(self):
4558                 """ exercise require dependencies """
4559 
4560                 self.image_create(self.rurl)
4561                 self.pkg("install pkg1@1.0")
4562                 self.pkg("verify  pkg1@1.0")
4563                 self.pkg("install pkg3@1.0")
4564                 self.pkg("verify  pkg3@1.0 pkg1@1.1")
4565 
4566         def test_exclude_dependencies(self):
4567                 """ exercise exclude dependencies """
4568 
4569                 self.image_create(self.rurl)
4570                 # install pkg w/ exclude dep.
4571                 self.pkg("install pkg4@1.0")
4572                 self.pkg("verify  pkg4@1.0")
4573                 # install pkg that is allowed by dep
4574                 self.pkg("install pkg1@1.0")
4575                 self.pkg("verify  pkg1@1.0")
4576                 # try to install disallowed pkg
4577                 self.pkg("install pkg1@1.1", exit=1)
4578                 self.pkg("uninstall '*'")
4579                 # install pkg
4580                 self.pkg("install pkg1@1.1")
4581                 # try to install pkg exclude dep on already
4582                 # installed pkg
4583                 self.pkg("install pkg4@1.0", exit=1)
4584                 self.pkg("uninstall '*'")
4585                 # install a package w/ both exclude
4586                 # and require dependencies
4587                 self.pkg("install pkg5")
4588                 self.pkg("verify pkg5@1.1 pkg1@1.0 ")
4589                 self.pkg("uninstall '*'")
4590                 # pick pkg to install that fits constraint
4591                 # of already installed pkg
4592                 self.pkg("install pkg2")
4593                 self.pkg("install pkg5")
4594                 self.pkg("verify pkg5@1.0.5 pkg1@1.0 pkg2")
4595                 self.pkg("uninstall '*'")
4596                 # install a package that requires updating
4597                 # existing package to avoid exclude
4598                 # dependency
4599                 self.pkg("install pkg6@1.0")
4600                 self.pkg("install pkg1@1.1")
4601                 self.pkg("verify pkg1@1.1 pkg6@1.1")
4602                 self.pkg("uninstall '*'")
4603                 # try to install two incompatible pkgs
4604                 self.pkg("install pkg1@1.1 pkg4@1.0", exit=1)
4605 
4606         def test_optional_dependencies(self):
4607                 """ check to make sure that optional dependencies are enforced
4608                 """
4609 
4610                 self.image_create(self.rurl)
4611                 self.pkg("install pkg1@1.0")
4612 
4613                 # pkg2 is optional, it should not have been installed
4614                 self.pkg("list pkg2", exit=1)
4615 
4616                 self.pkg("install pkg2@1.0")
4617 
4618                 # this should install pkg1@1.1 and upgrade pkg2 to pkg2@1.1
4619                 self.pkg("install pkg1")
4620                 self.pkg("list pkg2@1.1")
4621 
4622                 self.pkg("uninstall pkg2")
4623                 self.pkg("list pkg2", exit=1)
4624                 # this should not install pkg2@1.0 because of the optional
4625                 # dependency in pkg1
4626                 self.pkg("list pkg1@1.1")
4627                 self.pkg("install pkg2@1.0", exit=1)
4628 
4629         def test_incorporation_dependencies(self):
4630                 """ shake out incorporation dependencies """
4631 
4632                 self.image_create(self.rurl)
4633                 # simple pkg requiring controlling incorp
4634                 # should control pkgA_1 as well
4635                 self.pkg("install -v pkgA_0@1.0 pkgA_1")
4636                 self.pkg("list")
4637                 self.pkg("verify pkgA_0@1.0 pkgA_1@1.0 A_incorp@1.0")
4638                 self.pkg("install A_incorp@1.1")
4639                 self.pkg("list pkgA_0@1.1 pkgA_1@1.1 A_incorp@1.1")
4640                 self.pkg("uninstall '*'")
4641                 # try nested incorporations
4642                 self.pkg("install -v incorp@1.0 pkgA_0 pkgB_0")
4643                 self.pkg("list")
4644                 self.pkg("list incorp@1.0 pkgA_0@1.0 pkgB_0@1.0 A_incorp@1.0 B_incorp@1.0")
4645                 # try to break incorporation
4646                 self.pkg("install -v A_incorp@1.1", exit=1) # fixed by incorp@1.0
4647                 # try update (using '*' which also checks that the update all
4648                 # path is used when '*' is specified)
4649                 self.pkg("update -v '*'")
4650                 self.pkg("list incorp@1.2")
4651                 self.pkg("list pkgA_0@1.2")
4652                 self.pkg("list pkgB_0@1.2")
4653                 self.pkg("list A_incorp@1.2")
4654                 self.pkg("list B_incorp@1.2")
4655                 self.pkg("uninstall '*'")
4656                 # what happens when incorporation specified
4657                 # a package that isn't in the catalog
4658                 self.pkg("install bug_7394_incorp")
4659                 self.pkg("install pkg1", exit=1)
4660                 self.pkg("uninstall '*'")
4661                 # test pkg.depend.install-hold feature
4662                 self.pkg("install -v A_incorp@1.1  pkgA_1")
4663                 self.pkg("list pkgA_1@1.1")
4664                 self.pkg("list A_incorp@1.1")
4665                 # next attempt will fail because incorporations prevent motion
4666                 # even though explicit dependency exists from pkg to
4667                 # incorporation.
4668                 self.pkg("install pkgA_1@1.2", exit=1)
4669                 # test to see if we could install both; presence of incorp
4670                 # causes relaxation of pkg.depend.install-hold and also test
4671                 # that parsable output works when -n is used
4672                 self.pkg("install -n --parsable=0 A_incorp@1.2 pkgA_1@1.2")
4673                 self.assertEqualParsable(self.output, change_packages=[
4674                     [self.incorp_pkgs[2], self.incorp_pkgs[4]],
4675                     [self.leaf_pkgs[9], self.leaf_pkgs[17]]])
4676                 # this attempt also succeeds because pkg.depend.install-hold is
4677                 # relaxed since A_incorp is on command line
4678                 self.pkg("install A_incorp@1.2")
4679                 self.pkg("list pkgA_1@1.2")
4680                 self.pkg("list A_incorp@1.2")
4681                 # now demonstrate w/ version 1.2 subincorps that master incorp
4682                 # prevents upgrade since pkg.depend.install-hold of master != other incorps
4683                 self.pkg("install incorp@1.2")
4684                 self.pkg("install A_incorp@1.3", exit=1)
4685                 self.pkg("install incorp@1.3")
4686                 self.pkg("list pkgA_1@1.3")
4687                 self.pkg("list A_incorp@1.3")
4688 
4689         def test_conditional_dependencies(self):
4690                 """Get conditional dependencies working"""
4691                 self.image_create(self.rurl)
4692                 self.pkg("install pkg7@1.0")
4693                 self.pkg("verify")
4694                 self.pkg("list pkg6@1.1", exit=1) # should not be here
4695                 self.pkg("install -v pkg2@1.0")      # older version...
4696                 self.pkg("verify")
4697                 self.pkg("list pkg6@1.1", exit=1)
4698                 self.pkg("install -v pkg2@1.1")      # this triggers conditional dependency
4699                 self.pkg("verify")
4700                 self.pkg("list pkg6@1.1 pkg2@1.1 pkg7@1.0") # everyone is present
4701                 self.pkg("uninstall '*'")
4702 
4703                 self.pkg("install pkg2@1.1")  # install trigger
4704                 self.pkg("verify")
4705                 self.pkg("install pkg7@1.0")  # install pkg
4706                 self.pkg("list pkg6@1.1 pkg2@1.1 pkg7@1.0") # all here again
4707                 self.pkg("verify")
4708                 self.pkg("uninstall '*'")
4709 
4710                 # Test bug 18653
4711                 self.pkg("install osnet-incorporation@1.0 sun-solaris "
4712                     "perl-510 sun-solaris-510")
4713                 # Uninstall should fail because sun-solaris conditional
4714                 # dependency requires sun-solaris-510.
4715                 self.pkg("uninstall sun-solaris-510", exit=1)
4716                 # Uninstalling both the predicate and the target of the
4717                 # conditional dependency should work.
4718                 self.pkg("uninstall perl-510 sun-solaris-510")
4719                 self.pkg("install perl-510")
4720                 # Check that reject also works.
4721                 self.pkg("update --reject perl-510 --reject sun-solaris-510")
4722                 self.pkg("uninstall '*'")
4723 
4724                 # Verify that if the predicate of a conditional can be
4725                 # installed, but the consequent cannot, the package delivering
4726                 # the conditional dependency can still be installed.
4727                 self.pkg("install -v entire osnet-incorporation@1.1 "
4728                     "sun-solaris")
4729 
4730                 # Verify that the package incorporating a package that delivers
4731                 # a conditional for a consequent that cannot be installed can be
4732                 # removed.
4733                 self.pkg("uninstall -v entire")
4734 
4735         def test_require_any_dependencies(self):
4736                 """Get require-any dependencies working"""
4737                 self.image_create(self.rurl)
4738 
4739                 # test to see if solver will fail gracefully when no solution is
4740                 # possible and a require-any dependency is involved
4741                 self.pkg("install -vvv pkg-nosol-A pkg-nosol-E", exit=1)
4742 
4743                 # test to see if solver will pick one
4744                 self.pkg("install pkg8@1.0")  # install pkg
4745                 self.pkg("verify")
4746                 self.pkg("list pkg8@1.0 pkg9@1.0 pkg2@1.1", exit=3)
4747                 self.pkg("uninstall '*'")
4748 
4749                 # test to see if solver will be happy w/ renamed packages,
4750                 # already installed dependencies.
4751                 self.pkg("install pkg:/pkg2@1.1")
4752                 self.pkg("install pkg_need_rename")
4753                 self.pkg("install pkg8@1.0")
4754                 self.pkg("verify")
4755                 self.pkg("list pkg8@1.0 pkg2@1.1")
4756                 self.pkg("uninstall '*'")
4757 
4758                 # test to see if solver will install new verion of existing
4759                 # package rather than add new package
4760                 self.pkg("install pkg8@1.0 pkg9@1.0")  # install pkg
4761                 self.pkg("verify")
4762                 self.pkg("list pkg8@1.0 pkg9@1.0")
4763                 self.pkg("list pkg2@1.1", exit=1)
4764                 self.pkg("install pkg8 pkg9") # will fail w/o pkg9 on list
4765                 self.pkg("verify")
4766                 self.pkg("list pkg8@1.1 pkg9@1.1")
4767                 self.pkg("uninstall '*'")
4768 
4769                 # see if update works the same way
4770                 self.pkg("install pkg8@1.0 pkg9@1.0")  # install pkg
4771                 self.pkg("image-update")
4772                 self.pkg("list pkg8@1.1 pkg9@1.1")
4773                 self.pkg("uninstall '*'")
4774 
4775                 # test to see if uninstall is clever enough
4776                 self.pkg("install pkg8@1.0 pkg9@1.0")  # install pkg
4777                 self.pkg("verify")
4778                 self.pkg("list pkg8@1.0 pkg9@1.0")
4779                 self.pkg("uninstall pkg9@1.0")
4780                 self.pkg("list pkg2@1.1")
4781                 self.pkg("verify")
4782 
4783         def test_origin_dependencies(self):
4784                 """Get origin dependencies working"""
4785                 self.set_image(0)
4786                 self.image_create(self.rurl)
4787                 self.set_image(1)
4788                 self.image_create(self.rurl)
4789                 self.set_image(0)
4790                 # check install behavior
4791                 self.pkg("install pkg10@1.0")
4792                 self.pkg("install pkg10")
4793                 self.pkg("list pkg10@1.1")
4794                 self.pkg("install pkg10")
4795                 self.pkg("list pkg10@1.2")
4796                 self.pkg("uninstall '*'")
4797                 # check image-update behavior
4798                 self.pkg("install pkg10@1.0")
4799                 self.pkg("image-update")
4800                 self.pkg("list pkg10@1.1")
4801                 self.pkg("image-update")
4802                 self.pkg("list pkg10@1.2")
4803                 self.pkg("uninstall '*'")
4804                 # check that dependencies are ignored if
4805                 # dependency not present
4806                 self.pkg("install pkg10@1.2")
4807                 self.pkg("uninstall '*'")
4808                 # make sure attempts to force install don't work
4809                 self.pkg("install pkg10@1.0")
4810                 self.pkg("install pkg10@1.2", exit=1)
4811                 self.pkg("install pkg10@1.1")
4812                 self.pkg("install pkg10@1.2")
4813                 self.pkg("uninstall '*'")
4814                 # check origin root-image=true dependencies
4815                 # relies on SUNWcs in root image; make image 1 the root image
4816                 self.set_image(1)
4817                 self.pkg("install SUNWcs@0.5.11-0.75")
4818                 self.set_image(0)
4819                 live_root = self.img_path(1)
4820                 self.pkg("-D simulate_live_root=%s install pkg11@1.0" % \
4821                     live_root)
4822                 self.pkg("-D simulate_live_root=%s install pkg11@1.1" %
4823                     live_root, exit=1)
4824                 self.pkg("uninstall '*'")
4825 
4826         def test_parent_dependencies(self):
4827                 self.set_image(0)
4828                 self.image_create(self.rurl)
4829                 self.set_image(1)
4830                 self.image_create(self.rurl)
4831 
4832                 # attach c2p 1 -&gt; 0
4833                 self.pkg("attach-linked -p system:img1 %s" % self.img_path(0))
4834 
4835                 # try to install packages that have unmet parent dependencies
4836                 self.pkg("install pkg12@1.2", exit=EXIT_OOPS)
4837                 self.pkg("install pkg13@1.2", exit=EXIT_OOPS)
4838                 self.pkg("install pkg14@1.2", exit=EXIT_OOPS)
4839 
4840                 # install packages in parent
4841                 self.set_image(0)
4842                 self.pkg("install pkg12@1.1")
4843                 self.set_image(1)
4844 
4845                 # try to install packages that have unmet parent dependencies
4846                 self.pkg("install pkg12@1.2", exit=EXIT_OOPS)
4847                 self.pkg("install pkg13@1.2", exit=EXIT_OOPS)
4848                 self.pkg("install pkg14@1.2", exit=EXIT_OOPS)
4849 
4850                 # install packages in parent
4851                 self.set_image(0)
4852                 self.pkg("install pkg12@1.3")
4853                 self.set_image(1)
4854 
4855                 # try to install packages that have unmet parent dependencies
4856                 self.pkg("install pkg12@1.2", exit=EXIT_OOPS)
4857                 self.pkg("install pkg13@1.2", exit=EXIT_OOPS)
4858                 self.pkg("install pkg14@1.2", exit=EXIT_OOPS)
4859 
4860                 # install packages in parent
4861                 self.set_image(0)
4862                 self.pkg("update pkg12@1.2")
4863                 self.set_image(1)
4864 
4865                 # try to install packages that have unmet parent dependencies
4866                 self.pkg("install pkg14@1.2", exit=EXIT_OOPS)
4867 
4868                 # try to install packages that have satisfied parent deps
4869                 self.pkg("install pkg12@1.2")
4870                 self.pkg("verify")
4871                 self.pkg("uninstall pkg12@1.2")
4872                 self.pkg("install pkg13@1.2")
4873                 self.pkg("verify")
4874                 self.pkg("uninstall pkg13@1.2")
4875 
4876                 # install packages in parent
4877                 self.set_image(0)
4878                 self.pkg("install pkg13@1.2")
4879                 self.set_image(1)
4880 
4881                 # try to install packages that have satisfied parent deps
4882                 self.pkg("install pkg14@1.2")
4883                 self.pkg("verify")
4884                 self.pkg("uninstall pkg14@1.2")
4885 
4886 
4887 class TestMultipleDepots(pkg5unittest.ManyDepotTestCase):
4888         # Only start/stop the depot once (instead of for every test)
4889         persistent_setup = True
4890 
4891         foo10 = """
4892             open foo@1.0,5.11-0
4893             close"""
4894 
4895         bar10 = """
4896             open bar@1.0,5.11-0
4897             close"""
4898 
4899         moo10 = """
4900             open moo@1.0,5.11-0
4901             close"""
4902 
4903         quux10 = """
4904             open quux@1.0,5.11-0
4905             add depend type=optional fmri=optional@1.0
4906             close"""
4907 
4908         baz10 = """
4909             open baz@1.0,5.11-0
4910             add depend type=require fmri=corge@1.0
4911             close"""
4912 
4913         corge10 = """
4914             open corge@1.0,5.11-0
4915             close"""
4916 
4917         optional10 = """
4918             open optional@1.0,5.11-0
4919             close"""
4920 
4921         upgrade_p10 = """
4922             open upgrade-p@1.0,5.11-0
4923             close"""
4924 
4925         upgrade_p11 = """
4926             open upgrade-p@1.1,5.11-0
4927             close"""
4928 
4929         upgrade_np10 = """
4930             open upgrade-np@1.0,5.11-0
4931             close"""
4932 
4933         upgrade_np11 = """
4934             open upgrade-np@1.1,5.11-0
4935             close"""
4936 
4937         incorp_p10 = """
4938             open incorp-p@1.0,5.11-0
4939             add depend type=incorporate fmri=upgrade-p@1.0
4940             close"""
4941 
4942         incorp_p11 = """
4943             open incorp-p@1.1,5.11-0
4944             add depend type=incorporate fmri=upgrade-p@1.1
4945             close"""
4946 
4947         incorp_np10 = """
4948             open incorp-np@1.0,5.11-0
4949             add depend type=incorporate fmri=upgrade-np@1.0
4950             close"""
4951 
4952         incorp_np11 = """
4953             open incorp-np@1.1,5.11-0
4954             add depend type=incorporate fmri=upgrade-np@1.1
4955             close"""
4956 
4957         def setUp(self):
4958                 """ depot 1 gets foo and moo, depot 2 gets foo and bar,
4959                     depot 3 is empty, depot 4 gets upgrade_np@1.1
4960                     depot 5 gets corge10, depot6 is empty
4961                     depot7 is a copy of test1's repository for test3
4962                     depot1 is mapped to publisher test1 (preferred)
4963                     depot2 is mapped to publisher test2
4964                     depot3 is not mapped during setUp
4965                     depot4 is not mapped during setUp
4966                     depot5 is not mapped during setUp
4967                     depot6 is not mapped during setUp"""
4968 
4969                 # Two depots are intentionally started for some publishers.
4970                 pkg5unittest.ManyDepotTestCase.setUp(self, ["test1", "test2",
4971                     "test3", "test2", "test4", "test1", "test3"])
4972 
4973                 self.rurl1 = self.dcs[1].get_repo_url()
4974                 self.durl1 = self.dcs[1].get_depot_url()
4975                 self.pkgsend_bulk(self.rurl1, (self.foo10, self.moo10,
4976                     self.quux10, self.optional10, self.upgrade_p10,
4977                     self.upgrade_np11, self.incorp_p10, self.incorp_p11,
4978                     self.incorp_np10, self.incorp_np11, self.baz10,
4979                     self.corge10))
4980 
4981                 self.rurl2 = self.dcs[2].get_repo_url()
4982                 self.durl2 = self.dcs[2].get_depot_url()
4983                 self.pkgsend_bulk(self.rurl2, (self.foo10, self.bar10,
4984                     self.upgrade_p11, self.upgrade_np10, self.corge10))
4985 
4986                 self.rurl3 = self.dcs[3].get_repo_url()
4987 
4988                 self.rurl4 = self.dcs[4].get_repo_url()
4989                 self.pkgsend_bulk(self.rurl4, self.upgrade_np11)
4990 
4991                 self.rurl5 = self.dcs[5].get_repo_url()
4992                 self.pkgsend_bulk(self.rurl5, self.corge10)
4993 
4994                 self.rurl6 = self.dcs[6].get_repo_url()
4995                 self.rurl7 = self.dcs[7].get_repo_url()
4996 
4997                 # Copy contents of test1's repo to a repo for test3.
4998                 d1dir = self.dcs[1].get_repodir()
4999                 d2dir = self.dcs[7].get_repodir()
5000                 self.copy_repository(d1dir, d2dir, { "test1": "test3" })
5001                 self.dcs[7].get_repo(auto_create=True).rebuild()
5002 
5003                 # Create image and hence primary publisher
5004                 self.image_create(self.rurl1, prefix="test1")
5005 
5006                 # Create second publisher using depot #2
5007                 self.pkg("set-publisher -O " + self.rurl2 + " test2")
5008 
5009         def test_01_basics(self):
5010                 self.pkg("list -a")
5011 
5012                 # Install and uninstall moo (which is unique to depot 1)
5013                 self.pkg("install moo")
5014 
5015                 self.pkg("list")
5016                 self.pkg("uninstall moo")
5017 
5018                 # Install and uninstall bar (which is unique to depot 2)
5019                 self.pkg("install bar")
5020 
5021                 self.pkg("list")
5022 
5023                 self.pkg("uninstall bar")
5024 
5025                 # Install and uninstall foo (which is in both depots)
5026                 # In this case, we should select foo from depot 1, since
5027                 # it is preferred.
5028                 self.pkg("install foo")
5029 
5030                 self.pkg("list pkg://test1/foo")
5031 
5032                 self.pkg("uninstall foo")
5033 
5034         def test_02_basics(self):
5035                 """ Test install from an explicit preferred publisher """
5036                 self.pkg("install pkg://test1/foo")
5037                 self.pkg("list foo")
5038                 self.pkg("list pkg://test1/foo")
5039                 self.pkg("uninstall foo")
5040 
5041         def test_03_basics(self):
5042                 """ Test install from an explicit non-preferred publisher """
5043                 self.pkg("install pkg://test2/foo")
5044                 self.pkg("list foo")
5045                 self.pkg("list pkg://test2/foo")
5046                 self.pkg("uninstall foo")
5047 
5048         def test_04_upgrade_preferred_to_non_preferred(self):
5049                 """Install a package from the preferred publisher, and then
5050                 upgrade it, failing to implicitly switching to a non-preferred
5051                 publisher and then managing it explicitly"""
5052                 self.pkg("list -a upgrade-p")
5053                 self.pkg("install upgrade-p@1.0")
5054                 self.pkg("install upgrade-p@1.1", exit=1)
5055                 self.pkg("install pkg://test2/upgrade-p@1.1")
5056                 self.pkg("uninstall upgrade-p")
5057 
5058         def test_05_upgrade_non_preferred_to_preferred(self):
5059                 """Install a package from a non-preferred publisher, and then
5060                 try to upgrade it, failing to implicitly switch to the preferred
5061                 publisher and then succeed doing it explicitly."""
5062                 self.pkg("list -a upgrade-np")
5063                 self.pkg("install upgrade-np@1.0")
5064                 self.pkg("install upgrade-np@1.1", exit=1)
5065                 self.pkg("install pkg://test1/upgrade-np@1.1")
5066                 self.pkg("uninstall upgrade-np")
5067 
5068         def test_06_upgrade_preferred_to_non_preferred_incorporated(self):
5069                 """Install a package from the preferred publisher, and then
5070                 upgrade it, failing to implicitly switch to a non-preferred
5071                 publisher, when the package is constrained by an
5072                 incorporation, and then succeed when doing so explicitly"""
5073 
5074                 self.pkg("list -a upgrade-p incorp-p")
5075                 self.pkg("install incorp-p@1.0")
5076                 self.pkg("install upgrade-p")
5077                 self.pkg("install incorp-p@1.1", exit=1)
5078                 self.pkg("install incorp-p@1.1 pkg://test2/upgrade-p@1.1")
5079                 self.pkg("list upgrade-p@1.1")
5080                 self.pkg("uninstall '*'")
5081 
5082         def test_07_upgrade_non_preferred_to_preferred_incorporated(self):
5083                 """Install a package from the preferred publisher, and then
5084                 upgrade it, implicitly switching to a non-preferred
5085                 publisher, when the package is constrained by an
5086                 incorporation."""
5087                 self.pkg("list", exit=1)
5088                 self.pkg("list -a upgrade-np incorp-np")
5089                 self.pkg("install incorp-np@1.0")
5090                 self.pkg("install upgrade-np", exit=1)
5091                 self.pkg("uninstall '*'")
5092 
5093         def test_08_install_repository_access(self):
5094                 """Verify that packages can still be installed from a repository
5095                 even when any of the other repositories are not reachable and
5096                 --no-refresh is used."""
5097 
5098                 # Change the second publisher to point to an unreachable URI.
5099                 self.pkg("set-publisher --no-refresh -O http://test.invalid7 "
5100                     "test2")
5101 
5102                 # Verify that no packages are installed.
5103                 self.pkg("list", exit=1)
5104 
5105                 # Verify moo can not be installed (as only depot1 has it) since
5106                 # test2 cannot be reached (and needs a refresh).
5107                 self.pkg("install moo", exit=1)
5108 
5109                 # Verify moo can be installed (as only depot1 has it) even
5110                 # though test2 cannot be reached (and needs a refresh) if
5111                 # --no-refresh is used.
5112                 self.pkg("install --no-refresh moo")
5113 
5114                 self.pkg("uninstall moo")
5115 
5116                 # Reset the test2 publisher.
5117                 self.pkg("set-publisher -O %s test2" % self.rurl2)
5118 
5119                 # Install v1.0 of upgrade-np from test2 to prepare for
5120                 # update.
5121                 self.pkg("install upgrade-np@1.0")
5122 
5123                 # Set test1 to point to an unreachable URI.
5124                 self.pkg("set-publisher --no-refresh -O http://test.invalid7 "
5125                     "test1")
5126 
5127                 # Set test2 so that upgrade-np has a new version available
5128                 # even though test1's repository is not accessible.
5129                 self.pkg("set-publisher -O %s test2" % self.rurl4)
5130 
5131                 # Verify update does not work since test1 is unreachable
5132                 # even though upgrade-np@1.1 is available from test2.
5133                 self.pkg("update", exit=1)
5134 
5135                 # Verify update works even though test1 is unreachable
5136                 # since upgrade-np@1.1 is available from test2 if --no-refresh
5137                 # is used.
5138                 self.pkg("update --no-refresh")
5139 
5140                 # Now reset everything for the next test.
5141                 self.pkg("uninstall upgrade-np")
5142                 self.pkg("set-publisher --no-refresh -O %s test1" % self.rurl1)
5143                 self.pkg("set-publisher -O %s test2" % self.rurl2)
5144 
5145         def test_09_uninstall_from_wrong_publisher(self):
5146                 """Install a package from a publisher and try to remove it
5147                 using a different publisher name; this should fail."""
5148                 self.pkg("install foo")
5149                 self.pkg("uninstall pkg://test2/foo", exit=1)
5150                 # Check to make sure that uninstalling using the explicit
5151                 # publisher works
5152                 self.pkg("uninstall pkg://test1/foo")
5153 
5154         def test_10_install_after_publisher_removal(self):
5155                 """Install a package from a publisher that has an optional
5156                 dependency; then change the preferred publisher and remove the
5157                 original publisher and then verify that installing the package
5158                 again succeeds since it is essentially a no-op."""
5159                 self.pkg("install quux@1.0")
5160                 self.pkg("set-publisher -P test2")
5161                 self.pkg("unset-publisher test1")
5162                 self.pkg("list -avf")
5163 
5164                 # Attempting to install an already installed package should
5165                 # be a no-op even if the corresponding publisher no longer
5166                 # exists.
5167                 self.pkg("install quux@1.0", exit=4)
5168 
5169                 # Update should work if we don't see the optional
5170                 # dependency.
5171                 self.pkg("update", exit=4)
5172 
5173                 # Add back the installed package's publisher, but using a
5174                 # a repository with an empty catalog.  After that, attempt to
5175                 # install the package again, which should succeed even though
5176                 # the fmri is no longer in the publisher's catalog.
5177                 self.pkg("set-publisher -O %s test1" % self.rurl6)
5178                 self.pkg("install quux@1.0", exit=4)
5179                 self.pkg("info quux@1.0")
5180                 self.pkg("unset-publisher test1")
5181 
5182                 # Add a new publisher, with the same packages as the installed
5183                 # publisher.  Then, add back the installed package's publisher,
5184                 # but using an empty repository.  After that, attempt to install
5185                 # the package again, which should succeed since at least one
5186                 # publisher has the package in its catalog.
5187                 self.pkg("set-publisher -O %s test3" % self.rurl7)
5188                 self.pkg("set-publisher -O %s test1" % self.rurl6)
5189                 self.pkg("info -r pkg://test3/quux@1.0")
5190                 self.pkg("install quux@1.0", exit=4)
5191                 self.pkg("unset-publisher test1")
5192                 self.pkg("unset-publisher test3")
5193 
5194                 self.pkg("set-publisher -O %s test1" % self.rurl1)
5195                 self.pkg("info -r pkg://test1/quux@1.0")
5196                 self.pkg("unset-publisher test1")
5197 
5198                 # Add a new publisher, using the installed package publisher's
5199                 # repository.  After that, attempt to install the package again,
5200                 # which should simply result in a 'no updates necessary' exit
5201                 # code since the removed publisher's package is already the
5202                 # newest version available.
5203                 #
5204                 self.pkg("set-publisher -O %s test3" % self.rurl7)
5205                 self.pkg("install quux@1.0", exit=4)
5206                 self.pkg("unset-publisher test3")
5207 
5208                 # Change the image metadata back to where it was, in preparation
5209                 # for subsequent tests.
5210                 self.pkg("set-publisher -O %s -P test1" % self.rurl1)
5211 
5212                 # Remove the installed packages.
5213                 self.pkg("uninstall quux")
5214 
5215         def test_11_uninstall_after_preferred_publisher_change(self):
5216                 """Install a package from the preferred publisher, change the
5217                 preferred publisher, and attempt to remove the package."""
5218                 self.pkg("install foo@1.0")
5219                 self.pkg("set-publisher -P test2")
5220                 self.pkg("uninstall foo")
5221                 # Change the image metadata back to where it was, in preparation
5222                 # for the next test.
5223                 self.pkg("set-publisher -P test1")
5224 
5225         def test_12_uninstall_after_publisher_removal(self):
5226                 """Install a package from the preferred publisher, remove the
5227                 preferred publisher, and then evaluate whether an uninstall
5228                 would succeed regardless of whether its publisher still exists
5229                 or another publisher has the same fmri in its catalog."""
5230                 self.pkg("install foo@1.0")
5231                 self.pkg("set-publisher -P test2")
5232                 self.pkg("unset-publisher test1")
5233 
5234                 # Attempting to uninstall should work even if the corresponding
5235                 # publisher no longer exists.
5236                 self.pkg("uninstall -nv foo")
5237 
5238                 # Add back the installed package's publisher, but using a
5239                 # a repository with an empty catalog.  After that, attempt to
5240                 # uninstall the package again, which should succeed even though
5241                 # the fmri is no longer in the publisher's catalog.
5242                 self.pkg("set-publisher -O %s test1" % self.rurl6)
5243                 self.pkg("uninstall -nv foo")
5244                 self.pkg("unset-publisher test1")
5245 
5246                 # Add a new publisher, with a repository with the same packages
5247                 # as the installed publisher.  Then, add back the installed
5248                 # package's publisher using an empty repository.  After that,
5249                 # attempt to uninstall the package again, which should succeed
5250                 # even though the package's installed publisher is known, but
5251                 # doesn't have the package's fmri in its catalog, but the
5252                 # package's fmri is in a different publisher's catalog.
5253                 self.pkg("set-publisher -O %s test3" % self.rurl7)
5254                 self.pkg("set-publisher -O %s test1" % self.rurl6)
5255                 self.pkg("uninstall -nv foo")
5256                 self.pkg("unset-publisher test1")
5257                 self.pkg("unset-publisher test3")
5258 
5259                 # Add a new publisher, with a repository with the same packages
5260                 # as the installed publisher.  After that, attempt to uninstall
5261                 # the package again, which should succeed even though the fmri
5262                 # is only in a different publisher's catalog.
5263                 self.pkg("set-publisher -O %s test3" % self.rurl7)
5264                 self.pkg("uninstall -nv foo")
5265                 self.pkg("unset-publisher test3")
5266 
5267                 # Finally, actually remove the package.
5268                 self.pkg("uninstall -v foo")
5269 
5270                 # Change the image metadata back to where it was, in preparation
5271                 # for subsequent tests.
5272                 self.pkg("set-publisher -O %s -P test1" % self.rurl1)
5273 
5274         def test_13_non_preferred_multimatch(self):
5275                 """Verify that when multiple non-preferred publishers offer the
5276                 same package that the expected install behaviour occurs."""
5277 
5278                 self.pkg("set-publisher -P -O %s test3" % self.rurl3)
5279 
5280                 # make sure we look here first; tests rely on that
5281                 self.pkg("set-publisher --search-before=test2 test1")
5282                 self.pkg("publisher")
5283                 # First, verify that installing a package from a non-preferred
5284                 # publisher will cause its dependencies to be installed from the
5285                 # same publisher if the preferred publisher does not offer them.
5286                 self.pkg("list -a")
5287                 self.pkg("install pkg://test1/baz")
5288                 self.pkg("list")
5289                 self.pkg("info baz | grep test1")
5290                 self.pkg("info corge | grep test1")
5291                 self.pkg("uninstall baz corge")
5292 
5293                 # Next, verify that naming the specific publishers for a package
5294                 # and all of its dependencies will install the package from the
5295                 # specified sources instead of the same publisher the package is a
5296                 # dependency of.
5297                 self.pkg("install pkg://test1/baz pkg://test2/corge")
5298                 self.pkg("info baz | grep test1")
5299                 self.pkg("info corge | grep test2")
5300                 self.pkg("uninstall baz corge")
5301 
5302                 # Finally, cleanup for the next test.
5303                 self.pkg("set-publisher -P test1")
5304                 self.pkg("unset-publisher test3")
5305 
5306         def test_14_nonsticky_publisher(self):
5307                 """Test various aspects of the stick/non-sticky
5308                 behavior of publishers"""
5309 
5310                 # For ease of debugging
5311                 self.pkg("list -a")
5312                 # install from non-preferred repo explicitly
5313                 self.pkg("install pkg://test2/upgrade-np@1.0")
5314                 # Demonstrate that perferred publisher is not
5315                 # acceptable, since test2 is sticky by default
5316                 self.pkg("install upgrade-np@1.1", exit=1) # not right repo
5317                 # Check that we can proceed once test2 is not sticky
5318                 self.pkg("set-publisher --non-sticky test2")
5319                 self.pkg("install upgrade-np@1.1") # should work now
5320                 # Restore to pristine
5321                 self.pkg("set-publisher --sticky test2")
5322                 self.pkg("uninstall upgrade-np")
5323                 # Repeat the test w/ preferred
5324                 self.pkg("install upgrade-p")
5325                 self.pkg("set-publisher -P test2")
5326                 self.pkg("install upgrade-p@1.1", exit=1) #orig pub is sticky
5327                 self.pkg("set-publisher --non-sticky test1")  #not anymore
5328                 self.pkg("install upgrade-p@1.1")
5329                 self.pkg("set-publisher -P --sticky test1") # restore
5330                 self.pkg("uninstall '*'")
5331                 # Check  that search order can be overridden w/ explicit
5332                 # version specification...
5333                 self.pkg("install upgrade-p")
5334                 self.pkg("install upgrade-p@1.1", exit=1)
5335                 self.pkg("set-publisher --non-sticky test1")
5336                 self.pkg("install upgrade-p@1.1") # find match later on
5337                 self.pkg("set-publisher --sticky test1")
5338                 self.pkg("uninstall '*'")
5339 
5340         def test_15_nonsticky_update(self):
5341                 """Test to make sure update follows the same
5342                 publisher selection mechanisms as pkg install"""
5343 
5344                 # try update
5345                 self.pkg("install pkg://test2/upgrade-np@1.0")
5346                 self.pkg("update", exit=4)
5347                 self.pkg("list upgrade-np@1.0")
5348                 self.pkg("set-publisher --non-sticky test2")
5349                 self.pkg("publisher")
5350                 self.pkg("list -a upgrade-np")
5351                 self.pkg("update '*@*'")
5352                 self.pkg("list upgrade-np@1.1")
5353                 self.pkg("set-publisher --sticky test2")
5354                 self.pkg("uninstall '*'")
5355 
5356         def test_16_disabled_nonsticky(self):
5357                 """Test to make sure disabled publishers are
5358                 automatically made non-sticky, and after
5359                 being enabled keep their previous value
5360                 of stickiness"""
5361 
5362                 # For ease of debugging
5363                 self.pkg("list -a")
5364                 # install from non-preferred repo explicitly
5365                 self.pkg("install pkg://test2/upgrade-np@1.0")
5366                 # Demonstrate that perferred publisher is not
5367                 # acceptable, since test2 is sticky by default
5368                 self.pkg("install upgrade-np@1.1", exit=1) # not right repo
5369                 # Disable test2 and then we should be able to proceed
5370                 self.pkg("set-publisher --disable test2")
5371                 self.pkg("install upgrade-np@1.1")
5372                 self.pkg("publisher")
5373                 self.pkg("set-publisher --enable test2")
5374                 self.pkg("publisher")
5375                 self.pkg("publisher | egrep sticky", exit=1 )
5376 
5377         def test_17_dependency_is_from_deleted_publisher(self):
5378                 """Verify that packages installed from a publisher that has
5379                 been removed can still satisfy dependencies."""
5380 
5381                 self.pkg("set-publisher -O %s test4" % self.rurl5)
5382                 self.pkg("install pkg://test4/corge")
5383                 self.pkg("set-publisher --disable test2")
5384                 self.pkg("set-publisher --disable test4")
5385                 self.pkg("list -af")
5386                 self.pkg("publisher")
5387                 # this should work, since dependency is already installed
5388                 # even though it is from a disabled publisher
5389                 self.pkg("install baz@1.0")
5390 
5391         def test_18_upgrade_across_publishers(self):
5392                 """Verify that an install/update of specific packages when
5393                 there is a newer package version available works as expected.
5394                 """
5395 
5396                 # Ensure a new image is created.
5397                 self.image_create(self.rurl1, prefix="test1", destroy=True)
5398 
5399                 # Add second publisher using repository #2.
5400                 self.pkg("set-publisher -O " + self.rurl2 + " test2")
5401 
5402                 # Install older version of package from test1.
5403                 self.pkg("install pkg://test1/upgrade-p@1.0")
5404 
5405                 # Verify update of all packages results in nothing to do even
5406                 # after test2 is set as preferred.
5407                 self.pkg("set-publisher -P test2")
5408                 self.pkg("update -v", exit=4)
5409 
5410                 # Verify setting test1 as non-sticky would result in update.
5411                 self.pkg("set-publisher --non-sticky test1")
5412                 self.pkg("update -n")
5413 
5414                 # Verify update of 'upgrade-p' package will result in upgrade
5415                 # from 1.0 -&gt; 1.1.
5416                 self.pkg("update upgrade-p")
5417                 self.pkg("info pkg://test2/upgrade-p@1.1")
5418 
5419                 # Revert to 1.0 and verify install behaves the same.
5420                 self.pkg("update pkg://test1/upgrade-p@1.0")
5421                 self.pkg("install upgrade-p")
5422                 self.pkg("info pkg://test2/upgrade-p@1.1")
5423 
5424         def test_19_refresh_failure(self):
5425                 """Test that pkg client returns with exit code 1 when only one 
5426                 publisher is specified and it's not reachable (bug 7176158)."""
5427 
5428                 # Create private image for this test.
5429                 self.image_create(self.rurl1, prefix="test1") 
5430                 # Set origin to an invalid repo.
5431                 self.pkg("set-publisher --no-refresh -O http://test.invalid7 "
5432                     "test1")
5433 
5434                 # Check if install -n returns with exit code 1
5435                 self.pkg("install -n moo", exit=1)
5436 
5437 
5438 class TestImageCreateCorruptImage(pkg5unittest.SingleDepotTestCaseCorruptImage):
5439         """
5440         If a new essential directory is added to the format of an image it will
5441         be necessary to update this test suite. To update this test suite,
5442         decide in what ways it is necessary to corrupt the image (removing the
5443         new directory or file, or removing the some or all of contents of the
5444         new directory for example). Make the necessary changes in
5445         pkg5unittest.SingleDepotTestCaseCorruptImage to allow the needed
5446         corruptions, then add new tests to the suite below. Be sure to add
5447         tests for both Full and User images, and perhaps Partial images if
5448         situations are found where these behave differently than Full or User
5449         images.
5450         """
5451 
5452         # Only start/stop the depot once (instead of for every test)
5453         persistent_setup = True
5454 
5455         foo11 = """
5456             open foo@1.1,5.11-0
5457             add dir mode=0755 owner=root group=bin path=/lib
5458             add file tmp/libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1
5459             close """
5460 
5461         misc_files = [ "tmp/libc.so.1" ]
5462 
5463         PREFIX = "unset PKG_IMAGE; cd %s;"
5464 
5465         def setUp(self):
5466                 pkg5unittest.SingleDepotTestCaseCorruptImage.setUp(self)
5467                 self.make_misc_files(self.misc_files)
5468 
5469         def pkg(self, command, exit=0, comment="", use_img_root=True):
5470                 pkg5unittest.SingleDepotTestCaseCorruptImage.pkg(self, command,
5471                     exit=exit, comment=comment, prefix=self.PREFIX % self.dir,
5472                     use_img_root=use_img_root)
5473 
5474         # For each test:
5475         # A good image is created at $basedir/image
5476         # A corrupted image is created at $basedir/image/bad (called bad_dir
5477         #     in subsequent notes) in verious ways
5478         # The $basedir/image/bad/final directory is created and PKG_IMAGE
5479         #     is set to that dirctory.
5480 
5481         # Tests simulating a corrupted Full Image
5482 
5483         def test_empty_var_pkg(self):
5484                 """ Creates an empty bad_dir. """
5485 
5486                 self.pkgsend_bulk(self.rurl, self.foo11)
5487                 self.image_create(self.rurl)
5488 
5489                 self.dir = self.corrupt_image_create(self.rurl,
5490                     set(["publisher", "cfg_cache", "file", "pkg", "index"]),
5491                     ["var/pkg"])
5492 
5493                 self.pkg("install foo@1.1")
5494 
5495         def test_var_pkg_missing_publisher(self):
5496                 """ Creates bad_dir with only the publisher and known/state
5497                 dir missing. """
5498 
5499                 self.pkgsend_bulk(self.rurl, self.foo11)
5500                 self.image_create(self.rurl)
5501 
5502                 self.dir = self.corrupt_image_create(self.rurl,
5503                     set(["publisher_absent", "known_absent"]),
5504                     ["var/pkg"])
5505 
5506                 self.pkg("install foo@1.1")
5507 
5508         def test_var_pkg_missing_cfg_cache(self):
5509                 """ Creates bad_dir with only the cfg_cache file missing. """
5510 
5511                 self.pkgsend_bulk(self.rurl, self.foo11)
5512                 self.image_create(self.rurl)
5513 
5514                 self.dir = self.corrupt_image_create(self.rurl,
5515                     set(["cfg_cache_absent"]), ["var/pkg"])
5516 
5517                 self.pkg("-D simulate_live_root=%s install foo@1.1" %
5518                     self.backup_img_path(), use_img_root=False)
5519 
5520         def test_var_pkg_missing_index(self):
5521                 """ Creates bad_dir with only the index dir missing. """
5522 
5523                 self.pkgsend_bulk(self.rurl, self.foo11)
5524                 self.image_create(self.rurl)
5525 
5526                 self.dir = self.corrupt_image_create(self.rurl, set(
5527                     ["index_absent"]), ["var/pkg"])
5528 
5529                 self.pkg("install foo@1.1")
5530 
5531         def test_var_pkg_missing_publisher_empty(self):
5532                 """ Creates bad_dir with all dirs and files present, but
5533                 with an empty publisher and state/known dir.
5534                 """
5535 
5536                 self.pkgsend_bulk(self.rurl, self.foo11)
5537                 self.image_create(self.rurl)
5538 
5539                 self.dir = self.corrupt_image_create(self.rurl,
5540                     set(["publisher_empty", "known_empty"]), ["var/pkg"])
5541 
5542                 # This is expected to fail because it will see an empty
5543                 # publisher directory and not rebuild the files as needed
5544                 self.pkg("install --no-refresh foo@1.1", exit=1)
5545                 self.pkg("install foo@1.1")
5546 
5547         def test_var_pkg_missing_publisher_empty_hit_then_refreshed_then_hit(
5548             self):
5549                 """ Creates bad_dir with all dirs and files present, but with an
5550                 with an empty publisher and state/known dir. This is to ensure
5551                 that refresh will work, and that an install after the refresh
5552                 also works.
5553                 """
5554 
5555                 self.pkgsend_bulk(self.rurl, self.foo11)
5556                 self.image_create(self.rurl)
5557 
5558                 self.dir = self.corrupt_image_create(self.rurl,
5559                     set(["publisher_empty", "known_empty"]), ["var/pkg"])
5560 
5561                 self.pkg("install --no-refresh foo@1.1", exit=1)
5562                 self.pkg("refresh")
5563                 self.pkg("install foo@1.1")
5564 
5565 
5566         def test_var_pkg_left_alone(self):
5567                 """ Sanity check to ensure that the code for creating
5568                 a bad_dir creates a good copy other than what's specified
5569                 to be wrong. """
5570 
5571                 self.pkgsend_bulk(self.rurl, self.foo11)
5572                 self.image_create(self.rurl)
5573 
5574                 self.dir = self.corrupt_image_create(self.rurl, set(), ["var/pkg"])
5575 
5576                 self.pkg("install foo@1.1")
5577 
5578         # Tests simulating a corrupted User Image
5579 
5580         # These tests are duplicates of those above but instead of creating
5581         # a corrupt full image, they create a corrupt User image.
5582 
5583         def test_empty_ospkg(self):
5584                 """ Creates a corrupted image at bad_dir by creating empty
5585                 bad_dir.  """
5586 
5587                 self.pkgsend_bulk(self.rurl, self.foo11)
5588                 self.image_create(self.rurl)
5589 
5590                 self.dir = self.corrupt_image_create(self.rurl,
5591                     set(["publisher", "cfg_cache", "file", "pkg", "index"]),
5592                     [".org.opensolaris,pkg"])
5593 
5594                 self.pkg("install foo@1.1")
5595 
5596         def test_ospkg_missing_publisher(self):
5597                 """ Creates a corrupted image at bad_dir by creating bad_dir
5598                 with only the publisher and known/state dir missing. """
5599 
5600                 self.pkgsend_bulk(self.rurl, self.foo11)
5601                 self.image_create(self.rurl)
5602 
5603                 self.dir = self.corrupt_image_create(self.rurl,
5604                     set(["publisher_absent", "known_absent"]),
5605                         [".org.opensolaris,pkg"])
5606 
5607                 self.pkg("install foo@1.1")
5608 
5609         def test_ospkg_missing_cfg_cache(self):
5610                 """ Creates a corrupted image at bad_dir by creating
5611                 bad_dir with only the cfg_cache file missing.  """
5612 
5613                 self.pkgsend_bulk(self.rurl, self.foo11)
5614                 self.image_create(self.rurl)
5615 
5616                 self.dir = self.corrupt_image_create(self.rurl,
5617                     set(["cfg_cache_absent"]), [".org.opensolaris,pkg"])
5618 
5619                 self.pkg("-D simulate_live_root=%s install foo@1.1" %
5620                     self.backup_img_path(), use_img_root=False)
5621 
5622         def test_ospkg_missing_index(self):
5623                 """ Creates a corrupted image at bad_dir by creating
5624                 bad_dir with only the index dir missing. """
5625 
5626                 self.pkgsend_bulk(self.rurl, self.foo11)
5627                 self.image_create(self.rurl)
5628 
5629                 self.dir = self.corrupt_image_create(self.rurl, set(["index_absent"]),
5630                     [".org.opensolaris,pkg"])
5631 
5632                 self.pkg("install foo@1.1")
5633 
5634         def test_ospkg_missing_publisher_empty(self):
5635                 """ Creates a corrupted image at bad_dir by creating bad_dir
5636                 with all dirs and files present, but with an empty publisher
5637                 and known/state dir. """
5638 
5639                 self.pkgsend_bulk(self.rurl, self.foo11)
5640                 self.image_create(self.rurl)
5641 
5642                 self.dir = self.corrupt_image_create(self.rurl,
5643                     set(["publisher_empty", "known_empty"]),
5644                     [".org.opensolaris,pkg"])
5645 
5646                 self.pkg("install --no-refresh foo@1.1", exit=1)
5647 
5648         def test_ospkg_missing_publisher_empty_hit_then_refreshed_then_hit(self):
5649                 """ Creates bad_dir with all dirs and files present, but with
5650                 an empty publisher and known/state dir. This is to ensure that
5651                 refresh will work, and that an install after the refresh also
5652                 works.
5653                 """
5654 
5655                 self.pkgsend_bulk(self.rurl, self.foo11)
5656                 self.image_create(self.rurl)
5657 
5658                 self.dir = self.corrupt_image_create(self.rurl,
5659                     set(["publisher_empty", "known_empty"]),
5660                     [".org.opensolaris,pkg"])
5661 
5662                 self.pkg("install --no-refresh foo@1.1", exit=1)
5663                 self.pkg("refresh")
5664                 self.pkg("install foo@1.1")
5665 
5666         def test_ospkg_left_alone(self):
5667                 """ Sanity check to ensure that the code for creating
5668                 a bad_dir creates a good copy other than what's specified
5669                 to be wrong. """
5670 
5671                 self.pkgsend_bulk(self.rurl, self.foo11)
5672                 self.image_create(self.rurl)
5673 
5674                 self.dir = self.corrupt_image_create(self.rurl, set(),
5675                     [".org.opensolaris,pkg"])
5676 
5677                 self.pkg("install foo@1.1")
5678 
5679 
5680 class TestPkgInstallObsolete(pkg5unittest.SingleDepotTestCase):
5681         """Test cases for obsolete packages."""
5682 
5683         persistent_setup = True
5684         def test_basic(self):
5685                 foo1 = """
5686                     open foo@1
5687                     add dir path=usr mode=0755 owner=root group=root
5688                     close
5689                 """
5690                 # Obsolete packages can have metadata
5691                 foo2 = """
5692                     open foo@2
5693                     add set name=pkg.obsolete value=true
5694                     add set name=pkg.summary value="A test package"
5695                     close
5696                 """
5697 
5698                 fbar = """
5699                     open fbar@1
5700                     add depend type=require fmri=foo@2
5701                     close
5702                 """
5703 
5704                 qbar = """
5705                     open qbar@1
5706                     add depend type=require fmri=qux@2
5707                     close
5708                 """
5709 
5710                 qux1 = """
5711                     open qux@1
5712                     add dir path=usr mode=0755 owner=root group=root
5713                     close
5714                 """
5715 
5716                 qux2 = """
5717                     open qux@2
5718                     add set name=pkg.renamed value=true
5719                     add depend type=require fmri=foo@1
5720                     close
5721                 """
5722 
5723                 fred1 = """
5724                     open fred@1
5725                     add depend type=require fmri=foo
5726                     close
5727                 """
5728                 fred2 = """
5729                     open fred@2
5730                     close
5731                 """
5732 
5733                 self.pkgsend_bulk(self.rurl, (foo1, foo2, fbar, qbar, qux1,
5734                     qux2, fred1))
5735 
5736                 self.image_create(self.rurl)
5737 
5738                 # First install the non-obsolete version of foo
5739                 self.pkg("install foo@1")
5740                 self.pkg("list foo@1")
5741 
5742                 # Now install the obsolete version, and ensure it disappears (5)
5743                 self.pkg("install foo")
5744                 self.pkg("list foo", exit=1)
5745 
5746                 # Explicitly installing an obsolete package succeeds, but
5747                 # results in nothing on the system. (1)
5748                 self.pkg("install foo@2", exit=4)
5749                 self.pkg("list foo", exit=1)
5750 
5751                 # Installing a package with a dependency on an obsolete package
5752                 # fails. (2)
5753                 self.pkg("install fbar", exit=1)
5754 
5755                 # Installing a package with a dependency on a renamed package
5756                 # succeeds, leaving the first package and the renamed package on
5757                 # the system, as well as the empty, pre-renamed package. (3)
5758                 self.pkg("install qbar")
5759                 self.pkg("list qbar")
5760                 self.pkg("list foo@1")
5761                 self.pkg("list qux | grep -- i-r")
5762                 self.pkg("uninstall '*'") #clean up for next test
5763                 # A simple rename test: First install the pre-renamed version of
5764                 # qux.  Then install the renamed version, and see that the new
5765                 # package is installed, and the renamed package is installed,
5766                 # but marked renamed.  (4)
5767                 self.pkg("install qux@1")
5768                 self.pkg("install qux") # upgrades qux
5769                 self.pkg("list foo@1")
5770                 self.pkg("list qux", exit=1)
5771                 self.pkg("uninstall '*'") #clean up for next test
5772 
5773                 # Install a package that's going to be obsoleted and a package
5774                 # that depends on it.  Update the package to its obsolete
5775                 # version and see that it fails.  (6, sorta)
5776                 self.pkg("install foo@1 fred@1")
5777                 self.pkg("install foo@2", exit=1)
5778                 # now add a version of fred that doesn't require foo, and
5779                 # show that update works
5780                 self.pkgsend_bulk(self.rurl, fred2)
5781                 self.pkg("refresh")
5782                 self.pkg("install foo@2")
5783                 self.pkg("uninstall '*'") #clean up for next test
5784                 # test fix for bug 12898
5785                 self.pkg("install qux@1")
5786                 self.pkg("install fred@2")
5787                 self.pkg("list foo@1", exit=1) # should not be installed
5788                 self.pkg("install qux") #update
5789                 self.pkg("list foo@1")
5790 
5791         def test_basic_7a(self):
5792                 """Upgrade a package to a version with a dependency on a renamed
5793                 package.  A =&gt; A' (-&gt; Br (-&gt; C))"""
5794 
5795                 t7ap1_1 = """
5796                     open t7ap1@1
5797                     close
5798                 """
5799 
5800                 t7ap1_2 = """
5801                     open t7ap1@2
5802                     add depend type=require fmri=t7ap2
5803                     close
5804                 """
5805 
5806                 t7ap2_1 = """
5807                     open t7ap2@1
5808                     add set name=pkg.renamed value=true
5809                     add depend type=require fmri=t7ap3
5810                     close
5811                 """
5812 
5813                 t7ap3_1 = """
5814                     open t7ap3@1
5815                     close
5816                 """
5817 
5818                 self.pkgsend_bulk(self.rurl, t7ap1_1)
5819                 self.image_create(self.rurl)
5820 
5821                 self.pkg("install t7ap1")
5822 
5823                 self.pkgsend_bulk(self.rurl, (t7ap1_2, t7ap2_1, t7ap3_1))
5824 
5825                 self.pkg("refresh")
5826                 self.pkg("update")
5827                 self.pkg("list -af")
5828                 self.pkg("list t7ap2 | grep -- i-r")
5829                 self.pkg("list t7ap3")
5830 
5831         def test_basic_7b(self):
5832                 """Upgrade a package to a version with a dependency on a renamed
5833                 package.  Like 7a except package A starts off depending on B.
5834 
5835                 A (-&gt; B) =&gt; A' (-&gt; Br (-&gt; C))"""
5836 
5837                 t7bp1_1 = """
5838                     open t7bp1@1
5839                     add depend type=require fmri=t7bp2
5840                     close
5841                 """
5842 
5843                 t7bp1_2 = """
5844                     open t7bp1@2
5845                     add depend type=require fmri=t7bp2
5846                     close
5847                 """
5848 
5849                 t7bp2_1 = """
5850                     open t7bp2@1
5851                     close
5852                 """
5853 
5854                 t7bp2_2 = """
5855                     open t7bp2@1
5856                     add set name=pkg.renamed value=true
5857                     add depend type=require fmri=t7bp3
5858                     close
5859                 """
5860 
5861                 t7bp3_1 = """
5862                     open t7bp3@1
5863                     close
5864                 """
5865 
5866                 self.pkgsend_bulk(self.rurl, (t7bp1_1, t7bp2_1))
5867                 self.image_create(self.rurl)
5868 
5869                 self.pkg("install t7bp1")
5870 
5871                 self.pkgsend_bulk(self.rurl, (t7bp1_2, t7bp2_2, t7bp3_1))
5872 
5873                 self.pkg("refresh")
5874                 self.pkg("update")
5875                 self.pkg("list t7bp2 | grep -- i-r")
5876                 self.pkg("list t7bp3")
5877 
5878         def test_basic_7c(self):
5879                 """Upgrade a package to a version with a dependency on a renamed
5880                 package.  Like 7b, except package A doesn't change.
5881 
5882                 A (-&gt; B) =&gt; A (-&gt; Br (-&gt; C))"""
5883 
5884                 t7cp1_1 = """
5885                     open t7cp1@1
5886                     add depend type=require fmri=t7cp2
5887                     close
5888                 """
5889 
5890                 t7cp2_1 = """
5891                     open t7cp2@1
5892                     close
5893                 """
5894 
5895                 t7cp2_2 = """
5896                     open t7cp2@2
5897                     add set name=pkg.renamed value=true
5898                     add depend type=require fmri=t7cp3
5899                     close
5900                 """
5901 
5902                 t7cp3_1 = """
5903                     open t7cp3@1
5904                     close
5905                 """
5906 
5907                 self.pkgsend_bulk(self.rurl, (t7cp1_1, t7cp2_1))
5908                 self.image_create(self.rurl)
5909 
5910                 self.pkg("install t7cp1")
5911 
5912                 self.pkgsend_bulk(self.rurl, (t7cp2_2, t7cp3_1))
5913 
5914                 self.pkg("refresh")
5915                 self.pkg("update")
5916 
5917                 self.pkg("list t7cp2 | grep -- i-r")
5918                 self.pkg("list t7cp3")
5919 
5920         def test_basic_6a(self):
5921                 """Upgrade a package to a version with a dependency on an
5922                 obsolete package.  This version is unlikely to happen in real
5923                 life."""
5924 
5925                 t6ap1_1 = """
5926                     open t6ap1@1
5927                     close
5928                 """
5929 
5930                 t6ap1_2 = """
5931                     open t6ap1@2
5932                     add depend type=require fmri=t6ap2
5933                     close
5934                 """
5935 
5936                 t6ap2_1 = """
5937                     open t6ap2@1
5938                     add set name=pkg.obsolete value=true
5939                     close
5940                 """
5941 
5942 
5943                 self.pkgsend_bulk(self.rurl, t6ap1_1)
5944                 self.image_create(self.rurl)
5945 
5946                 self.pkg("install t6ap1")
5947 
5948                 self.pkgsend_bulk(self.rurl, (t6ap1_2, t6ap2_1))
5949 
5950                 self.pkg("refresh")
5951                 self.pkg("update", exit=4) # does nothing
5952                 self.pkg("list t6ap1")
5953 
5954         def test_basic_6b(self):
5955                 """Install a package with a dependency, and update after
5956                 publishing updated packages for both, but where the dependency
5957                 has become obsolete."""
5958 
5959                 t6ap1_1 = """
5960                     open t6ap1@1
5961                     add depend type=require fmri=t6ap2
5962                     close
5963                 """
5964 
5965                 t6ap1_2 = """
5966                     open t6ap1@2
5967                     add depend type=require fmri=t6ap2
5968                     close
5969                 """
5970 
5971                 t6ap2_1 = """
5972                     open t6ap2@1
5973                     close
5974                 """
5975 
5976                 t6ap2_2 = """
5977                     open t6ap2@2
5978                     add set name=pkg.obsolete value=true
5979                     close
5980                 """
5981 
5982                 self.pkgsend_bulk(self.rurl, (t6ap1_1, t6ap2_1))
5983                 self.image_create(self.rurl)
5984 
5985                 self.pkg("install t6ap1")
5986                 self.pkg("list")
5987 
5988                 self.pkgsend_bulk(self.rurl, (t6ap1_2, t6ap2_2))
5989 
5990                 self.pkg("refresh")
5991                 self.pkg("update")
5992                 self.pkg("list t6ap1@2 t6ap2@1")
5993 
5994         def test_basic_8a(self):
5995                 """Upgrade a package to an obsolete leaf version when another
5996                 depends on it."""
5997 
5998                 t8ap1_1 = """
5999                     open t8ap1@1
6000                     close
6001                 """
6002 
6003                 t8ap1_2 = """
6004                     open t8ap1@2
6005                     add set name=pkg.obsolete value=true
6006                     close
6007                 """
6008 
6009                 t8ap2_1 = """
6010                     open t8ap2@1
6011                     add depend type=require fmri=t8ap1
6012                     close
6013                 """
6014 
6015                 self.pkgsend_bulk(self.rurl, (t8ap1_1, t8ap2_1))
6016                 self.image_create(self.rurl)
6017 
6018                 self.pkg("install t8ap2")
6019 
6020                 self.pkgsend_bulk(self.rurl, t8ap1_2)
6021 
6022                 self.pkg("refresh")
6023                 self.pkg("update", exit=4) # does nothing
6024                 self.pkg("list  t8ap2@1")
6025 
6026         def test_basic_13a(self):
6027                 """Publish an package with a dependency, then publish both as
6028                 obsolete, update, and see that both packages have gotten
6029                 removed."""
6030 
6031                 t13ap1_1 = """
6032                     open t13ap1@1
6033                     add depend type=require fmri=t13ap2
6034                     close
6035                 """
6036 
6037                 t13ap1_2 = """
6038                     open t13ap1@2
6039                     add set name=pkg.obsolete value=true
6040                     close
6041                 """
6042 
6043                 t13ap2_1 = """
6044                     open t13ap2@1
6045                     close
6046                 """
6047 
6048                 t13ap2_2 = """
6049                     open t13ap2@2
6050                     add set name=pkg.obsolete value=true
6051                     close
6052                 """
6053 
6054                 self.pkgsend_bulk(self.rurl, (t13ap1_1, t13ap2_1))
6055                 self.image_create(self.rurl)
6056 
6057                 self.pkg("install t13ap1")
6058 
6059                 self.pkgsend_bulk(self.rurl, (t13ap1_2, t13ap2_2))
6060 
6061                 self.pkg("refresh")
6062                 self.pkg("update")
6063                 self.pkg("list", exit=1)
6064 
6065         def test_basic_11(self):
6066                 """Install a package with an ambiguous name, where only one
6067                 match is non-obsolete."""
6068 
6069                 t11p1 = """
6070                     open netbeans@1
6071                     add set name=pkg.obsolete value=true
6072                     close
6073                 """
6074 
6075                 t11p2 = """
6076                     open developer/netbeans@1
6077                     close
6078                 """
6079 
6080                 self.pkgsend_bulk(self.rurl, (t11p1, t11p2))
6081                 self.image_create(self.rurl)
6082 
6083                 self.pkg("install netbeans")
6084                 self.pkg("list pkg:/developer/netbeans")
6085                 self.pkg("list pkg:/netbeans", exit=1)
6086 
6087         def test_basic_11a(self):
6088                 """Install a package using an ambiguous name where
6089                 pkg is renamed to another package, but not the
6090                 conflicting one"""
6091 
6092                 t11p1 = """
6093                     open netbonze@1
6094                     add set name=pkg.renamed value=true
6095                     add depend type=require fmri=SUNWnetbonze
6096                     close
6097                 """
6098 
6099                 t11p2 = """
6100                     open developer/netbonze@1
6101                     close
6102                 """
6103 
6104                 t11p3 = """
6105                     open SUNWnetbonze@1
6106                     close
6107                 """
6108 
6109                 self.pkgsend_bulk(self.rurl, (t11p1, t11p2, t11p3))
6110                 self.image_create(self.rurl)
6111 
6112                 self.pkg("install netbonze", exit=1)
6113 
6114         def test_basic_11b(self):
6115                 """Install a package using an ambiguous name where only one
6116                 match is non-renamed, and the renamed match is renamed to the
6117                 other."""
6118 
6119                 t11p1 = """
6120                     open netbooze@1
6121                     close
6122                 """
6123 
6124                 t11p2 = """
6125                     open netbooze@2
6126                     add set name=pkg.renamed value=true
6127                     add depend type=require fmri=developer/netbooze
6128                     close
6129                 """
6130 
6131                 t11p3 = """
6132                     open developer/netbooze@2
6133                     close
6134                 """
6135 
6136                 t11p4 = """
6137                     open developer/netbooze@3
6138                     add depend type=require fmri=developer/missing
6139                     close
6140                 """
6141 
6142                 self.pkgsend_bulk(self.rurl, (t11p1, t11p2, t11p3, t11p4))
6143                 self.image_create(self.rurl)
6144 
6145                 self.pkg("install netbooze")
6146                 self.pkg("list pkg:/developer/netbooze")
6147                 self.pkg("list pkg:/netbooze", exit=1)
6148 
6149 
6150         def test_basic_12(self):
6151                 """Upgrade a package across a rename to an ambiguous name."""
6152 
6153                 t12p1_1 = """
6154                     open netbeenz@1
6155                     close
6156                 """
6157 
6158                 t12p1_2 = """
6159                     open netbeenz@2
6160                     add set name=pkg.renamed value=true
6161                     add depend type=require fmri=pkg:/developer/netbeenz
6162                     close
6163                 """
6164 
6165                 t12p2_1 = """
6166                     open developer/netbeenz@1
6167                     close
6168                 """
6169 
6170                 self.pkgsend_bulk(self.rurl, t12p1_1)
6171                 self.image_create(self.rurl)
6172 
6173                 self.pkg("install netbeenz")
6174 
6175                 self.pkgsend_bulk(self.rurl, (t12p1_2, t12p2_1))
6176 
6177                 self.pkg("refresh")
6178                 self.pkg("update -v")
6179                 self.pkg("list pkg:/developer/netbeenz | grep -- i--")
6180                 self.pkg("list pkg:/netbeenz", exit=1)
6181 
6182         def test_remove_renamed(self):
6183                 """If a renamed package has nothing depending on it, it should
6184                 be removed."""
6185 
6186                 p1_1 = """
6187                     open remrenA@1
6188                     close
6189                 """
6190 
6191                 p1_2 = """
6192                     open remrenA@2
6193                     add set name=pkg.renamed value=true
6194                     add depend type=require fmri=pkg:/remrenB
6195                     close
6196                 """
6197 
6198                 p2_1 = """
6199                     open remrenB@1
6200                     close
6201                 """
6202 
6203                 p3_1 = """
6204                     open remrenC@1
6205                     add depend type=require fmri=pkg:/remrenA
6206                     close
6207                 """
6208 
6209                 self.pkgsend_bulk(self.rurl, p1_1)
6210                 self.image_create(self.rurl)
6211 
6212                 self.pkg("install remrenA")
6213 
6214                 self.pkgsend_bulk(self.rurl, (p1_2, p2_1, p3_1))
6215 
6216                 self.pkg("refresh")
6217                 self.pkg("update")
6218                 self.pkg("list remrenA", exit=1)
6219 
6220                 # But if there is something depending on the renamed package, it
6221                 # can't be removed.
6222                 self.pkg("uninstall remrenB")
6223 
6224                 self.pkg("install remrenA@1 remrenC")
6225                 self.pkg("update")
6226                 self.pkg("list remrenA")
6227 
6228         def test_chained_renames(self):
6229                 """If there are multiple renames, make sure we delete as much
6230                 as possible, but no more."""
6231 
6232                 A1 = """
6233                     open chained_A@1
6234                     close
6235                 """
6236 
6237                 A2 = """
6238                     open chained_A@2
6239                     add set name=pkg.renamed value=true
6240                     add depend type=require fmri=pkg:/chained_B@2
6241                     close
6242                 """
6243 
6244                 B2 = """
6245                     open chained_B@2
6246                     add set name=pkg.renamed value=true
6247                     add depend type=require fmri=pkg:/chained_C@2
6248                     close
6249                 """
6250 
6251                 C2 = """
6252                     open chained_C@2
6253                     close
6254                 """
6255 
6256                 X = """
6257                     open chained_X@1
6258                     add depend type=require fmri=pkg:/chained_A
6259                     close
6260                 """
6261 
6262                 Y = """
6263                     open chained_Y@1
6264                     add depend type=require fmri=pkg:/chained_B
6265                     close
6266                 """
6267 
6268                 Z = """
6269                     open chained_Z@1
6270                     close
6271                 """
6272 
6273                 self.pkgsend_bulk(self.rurl, (A1, A2, B2, C2, X, Y, Z))
6274 
6275                 self.image_create(self.rurl)
6276 
6277                 self.pkg("install chained_A@1 chained_X chained_Z")
6278                 for p in ["chained_A@1", "chained_X@1"]:
6279                         self.pkg("list %s" % p)
6280                 self.pkg("update")
6281 
6282                 for p in ["chained_A@2", "chained_X@1", "chained_B@2",
6283                     "chained_C@2", "chained_Z"]:
6284                         self.pkg("list %s" % p)
6285 
6286                 self.pkg("uninstall chained_X")
6287 
6288                 for p in ["chained_C@2", "chained_Z"]:
6289                         self.pkg("list %s" % p)
6290 
6291                 # make sure renamed pkgs no longer needed are uninstalled
6292                 for p in ["chained_A@2", "chained_B@2"]:
6293                         self.pkg("list %s" % p, exit=1)
6294 
6295         def test_unobsoleted(self):
6296                 """Ensure that the existence of an obsolete package version
6297                 does not prevent the system from upgrading to or installing
6298                 a resurrected version."""
6299 
6300                 pA_1 = """
6301                     open reintroA@1
6302                     close
6303                 """
6304 
6305                 pA_2 = """
6306                     open reintroA@2
6307                     add set name=pkg.obsolete value=true
6308                     close
6309                 """
6310 
6311                 pA_3 = """
6312                     open reintroA@3
6313                     close
6314                 """
6315 
6316                 pB_1 = """
6317                     open reintroB@1
6318                     add depend type=require fmri=pkg:/reintroA@1
6319                     close
6320                 """
6321 
6322                 pB_2 = """
6323                     open reintroB@2
6324                     close
6325                 """
6326 
6327                 pB_3 = """
6328                     open reintroB@3
6329                     add depend type=require fmri=pkg:/reintroA@3
6330                     close
6331                 """
6332 
6333                 self.pkgsend_bulk(self.rurl, (pA_1, pA_2, pA_3, pB_1, pB_2,
6334                     pB_3))
6335                 self.image_create(self.rurl)
6336 
6337                 # Check installation of an unobsoleted package with no
6338                 # dependencies.
6339 
6340                 # Testing reintroA@1 -&gt; reintroA@3 with update
6341                 self.pkg("install reintroA@1")
6342                 self.pkg("refresh")
6343                 self.pkg("update")
6344                 self.pkg("list reintroA@3")
6345                 self.pkg("uninstall reintroA")
6346 
6347                 # Testing reintroA@1 -&gt; reintroA@3 with install
6348                 self.pkg("install reintroA@1")
6349                 self.pkg("install reintroA@3")
6350                 self.pkg("list reintroA@3")
6351                 self.pkg("uninstall reintroA")
6352 
6353                 # Testing empty image -&gt; reintroA@3 with install
6354                 self.pkg("install reintroA@3")
6355                 self.pkg("list reintroA@3")
6356                 self.pkg("uninstall reintroA")
6357 
6358                 # Testing reintroA@1 -&gt; reintroA@2 -&gt; reintroA@3 with install
6359                 self.pkg("install reintroA@1")
6360                 self.pkg("install reintroA@2")
6361                 self.pkg("install reintroA@3")
6362                 self.pkg("list reintroA@3")
6363                 self.pkg("uninstall reintroA")
6364 
6365                 # Check installation of a package with an unobsoleted
6366                 # dependency.
6367 
6368                 # Testing reintroB@1 -&gt; reintroB@3 with update
6369                 self.pkg("install reintroB@1")
6370                 self.pkg("refresh")
6371                 self.pkg("update")
6372                 self.pkg("list reintroB@3")
6373                 self.pkg("list reintroA@3")
6374                 self.pkg("uninstall reintroB reintroA")
6375 
6376                 # Testing reintroB@1 -&gt; reintroB@3 with install
6377                 self.pkg("install reintroB@1")
6378                 self.pkg("install reintroB@3")
6379                 self.pkg("list reintroB@3")
6380                 self.pkg("list reintroA@3")
6381                 self.pkg("uninstall reintroB reintroA")
6382 
6383                 # Testing empty image -&gt; reintroB@3 with install
6384                 self.pkg("install reintroB@3")
6385                 self.pkg("list reintroB@3")
6386                 self.pkg("list reintroA@3")
6387                 self.pkg("uninstall reintroB reintroA")
6388 
6389                 # Testing reintroB@1 -&gt; reintroB@2 -&gt; reintroB@3 with install
6390                 self.pkg("install reintroB@1")
6391                 self.pkg("install reintroB@2")
6392                 self.pkg("install reintroB@3")
6393                 self.pkg("list reintroB@3")
6394                 self.pkg("list reintroA@3")
6395                 self.pkg("uninstall reintroB reintroA")
6396 
6397         def test_incorp_1(self):
6398                 """We should be able to incorporate an obsolete package."""
6399 
6400                 p1_1 = """
6401                     open inc1p1@1
6402                     add depend type=incorporate fmri=inc1p2@1
6403                     close
6404                 """
6405 
6406                 p2_1 = """
6407                     open inc1p2@1
6408                     add set name=pkg.obsolete value=true
6409                     close
6410                 """
6411 
6412                 self.pkgsend_bulk(self.rurl, (p1_1, p2_1))
6413                 self.image_create(self.rurl)
6414 
6415                 self.pkg("install inc1p1")
6416                 self.pkg("install inc1p2", exit=4)
6417 
6418                 self.pkg("list inc1p2", exit=1)
6419 
6420         def test_incorp_2(self):
6421                 """We should be able to continue incorporating a package when it
6422                 becomes obsolete on upgrade."""
6423 
6424                 p1_1 = """
6425                     open inc2p1@1
6426                     add depend type=incorporate fmri=inc2p2@1
6427                     close
6428                 """
6429 
6430                 p1_2 = """
6431                     open inc2p1@2
6432                     add depend type=incorporate fmri=inc2p2@2
6433                     close
6434                 """
6435 
6436                 p2_1 = """
6437                     open inc2p2@1
6438                     close
6439                 """
6440 
6441                 p2_2 = """
6442                     open inc2p2@2
6443                     add set name=pkg.obsolete value=true
6444                     close
6445                 """
6446 
6447                 self.pkgsend_bulk(self.rurl, (p1_1, p2_1))
6448                 self.image_create(self.rurl)
6449 
6450                 self.pkg("install inc2p1 inc2p2")
6451 
6452                 self.pkgsend_bulk(self.rurl, (p1_2, p2_2))
6453 
6454                 self.pkg("refresh")
6455                 self.pkg("list -afv")
6456                 self.pkg("update -v")
6457                 self.pkg("list inc2p2", exit=1)
6458 
6459 
6460 class TestPkgInstallMultiObsolete(pkg5unittest.ManyDepotTestCase):
6461         """Tests involving obsolete packages and multiple publishers."""
6462 
6463         obs = """
6464             open stem@1
6465             add set name=pkg.obsolete value=true
6466             close
6467         """
6468 
6469         nonobs = """
6470             open stem@1
6471             close
6472         """
6473 
6474         persistent_setup = True
6475 
6476         def setUp(self):
6477                 pkg5unittest.ManyDepotTestCase.setUp(self, ["test1", "test2"])
6478                 self.rurl1 = self.dcs[1].get_repo_url()
6479                 self.rurl2 = self.dcs[2].get_repo_url()
6480 
6481         def test_01(self):
6482                 """If an obsolete package is found in a preferred publisher and
6483                 a non-obsolete package of the same name is found in a
6484                 non-preferred publisher, pick the preferred pub as usual """
6485 
6486                 self.pkgsend_bulk(self.rurl1, self.obs)
6487                 self.pkgsend_bulk(self.rurl2, self.nonobs)
6488 
6489                 self.image_create(self.rurl1, prefix="test1")
6490                 self.pkg("set-publisher -O " + self.rurl2 + " test2")
6491                 self.pkg("list -a")
6492 
6493                 self.pkg("install stem", exit=4) # noting to do since it's obs
6494                 # We should choose the obsolete package, which means nothing
6495                 # gets installed.
6496                 self.pkg("list", exit=1)
6497 
6498         def test_02(self):
6499                 """Same as test_01, but now we have ambiguity in the package
6500                 names.  While at first blush we might follow the same rule as in
6501                 test_01 (choose the preferred publisher), in this case, we can't
6502                 figure out which package from the preferred publisher we want,
6503                 so the choice already isn't as straightforward, so we choose the
6504                 non-obsolete package."""
6505 
6506                 lobs = """
6507                     open some/stem@1
6508                     add set name=pkg.obsolete value=true
6509                     close
6510                 """
6511 
6512                 self.pkgsend_bulk(self.rurl1, (self.obs, lobs))
6513                 self.pkgsend_bulk(self.rurl2, (self.nonobs, lobs))
6514 
6515                 self.image_create(self.rurl1, prefix="test1")
6516                 self.pkg("set-publisher -O " + self.rurl2 + " test2")
6517 
6518                 self.pkg("install stem", exit=1)
6519 
6520 
6521 class TestPkgInstallLicense(pkg5unittest.SingleDepotTestCase):
6522         """Tests involving one or more packages that require license acceptance
6523         or display."""
6524 
6525         persistent_depot = True
6526 
6527         # Tests in this suite use the read only data directory.
6528         need_ro_data = True
6529 
6530         baz10 = """
6531             open baz@1.0,5.11-0
6532             add license copyright.baz license=copyright.baz
6533             close """
6534 
6535         # First iteration has just a copyright.
6536         licensed10 = """
6537             open licensed@1.0,5.11-0
6538             add depend type=require fmri=baz@1.0
6539             add license copyright.licensed license=copyright.licensed
6540             close """
6541 
6542         # Second iteration has copyright that must-display and a new license
6543         # that doesn't require acceptance.
6544         licensed12 = """
6545             open licensed@1.2,5.11-0
6546             add depend type=require fmri=baz@1.0
6547             add file libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1
6548             add license copyright.licensed license=copyright.licensed must-display=True
6549             add license license.licensed license=license.licensed
6550             close """
6551 
6552         # Third iteration now requires acceptance of license.
6553         licensed13 = """
6554             open licensed@1.3,5.11-0
6555             add depend type=require fmri=baz@1.0
6556             add file libc.so.1 mode=0555 owner=root group=bin path=/lib/libc.so.1
6557             add license copyright.licensed license=copyright.licensed must-display=True
6558             add license license.licensed license=license.licensed must-accept=True
6559             close """
6560 
6561         misc_files = ["copyright.baz", "copyright.licensed", "libc.so.1",
6562             "license.licensed", "license.licensed.addendum"]
6563 
6564         # Packages with copyright in non-ascii character
6565         nonascii10 = """
6566             open nonascii@1.0,5.11-0
6567             add license 88591enc.copyright license=copyright
6568             close """
6569 
6570         # Packages with copyright in non-ascii character
6571         utf8enc10 = """
6572             open utf8enc@1.0,5.11-0
6573             add license utf8enc.copyright license=copyright
6574             close """
6575 
6576         # Packages with copyright in unsupported character set
6577         unsupported10 = """
6578             open unsupported@1.0,5.11-0
6579             add license unsupported.copyright license=copyright
6580             close """
6581 
6582         def setUp(self):
6583                 pkg5unittest.SingleDepotTestCase.setUp(self, publisher="bobcat")
6584                 self.make_misc_files(self.misc_files)
6585 
6586                 # Use license with latin1 i.e 88591 encoding
6587                 n_copyright = os.path.join(self.ro_data_root,
6588                     "88591enc.copyright")
6589                 self.make_misc_files({"88591enc.copyright": n_copyright})
6590 
6591                 # Use utf-8 encoding license
6592                 utf_copyright = os.path.join(self.ro_data_root,
6593                     "utf8enc.copyright")
6594                 self.make_misc_files({"utf8enc.copyright": utf_copyright})
6595 
6596                 # Use unsupported license
6597                 u_copyright = os.path.join(self.ro_data_root,
6598                     "unsupported.copyright")
6599                 self.make_misc_files({"unsupported.copyright": u_copyright})
6600 
6601                 self.plist = self.pkgsend_bulk(self.rurl, (self.licensed10,
6602                     self.licensed12, self.licensed13, self.baz10,
6603                     self.nonascii10, self.utf8enc10, self.unsupported10))
6604 
6605 
6606         def test_01_install_update(self):
6607                 """Verifies that install and update handle license
6608                 acceptance and display."""
6609 
6610                 self.image_create(self.rurl, prefix="bobcat")
6611 
6612                 # First, test the basic install case to see if a license that
6613                 # does not require viewing or acceptance will be installed.
6614                 self.pkg("install --parsable=0 licensed@1.0")
6615                 self.assertEqualParsable(self.output,
6616                     add_packages=[self.plist[3], self.plist[0]], licenses=[
6617                         [self.plist[3], None,
6618                             [self.plist[3], "copyright.baz", "copyright.baz",
6619                             False, False]],
6620                         [self.plist[0], None,
6621                             [self.plist[0], "copyright.licensed",
6622                             "copyright.licensed", False, False]
6623                         ]])
6624                 self.pkg("list")
6625                 self.pkg("info licensed@1.0 baz@1.0")
6626 
6627                 # Verify that --licenses include the license in output.
6628                 self.pkg("install -n --licenses licensed@1.2 | "
6629                     "grep 'license.licensed'")
6630 
6631                 # Verify that licenses that require display are included in
6632                 # -n output even if --licenses is not provided.
6633                 self.pkg("install -n licensed@1.2 | grep 'copyright.licensed'")
6634 
6635                 # Next, check that an upgrade succeeds when a license requires
6636                 # display and that the license will be displayed.
6637                 self.pkg("install --parsable=0 licensed@1.2")
6638                 self.assertEqualParsable(self.output,
6639                     change_packages=[[self.plist[0], self.plist[1]]], licenses=[
6640                         [self.plist[1],
6641                             None,
6642                             [self.plist[1], "license.licensed",
6643                             "license.licensed", False, False]],
6644                         [self.plist[1],
6645                             [self.plist[0], "copyright.licensed",
6646                             "copyright.licensed", False, False],
6647                             [self.plist[1], "copyright.licensed",
6648                             "copyright.licensed", False, True]]])
6649 
6650                 # Next, check that an update fails if the user has not
6651                 # specified --accept and a license requires acceptance.
6652                 self.pkg("update -v", exit=6)
6653                 # Check that asking for parsable output doesn't change this
6654                 # requirement.
6655                 self.pkg("update --parsable=0", exit=6)
6656 
6657                 # Verify that licenses are not included in -n output if
6658                 # --licenses is not provided.
6659                 self.pkg("update -n | grep 'copyright.licensed", exit=1)
6660 
6661                 # Verify that --licenses include the license in output.
6662                 self.pkg("update -n --licenses | "
6663                     "grep 'license.licensed'")
6664 
6665                 # Next, check that an update succeeds if the user has
6666                 # specified --accept and a license requires acceptance.
6667                 self.pkg("update --parsable=0 --accept")
6668                 self.assertEqualParsable(self.output,
6669                     change_packages=[[self.plist[1], self.plist[2]]], licenses=[
6670                         [self.plist[2],
6671                             [self.plist[1], "license.licensed",
6672                             "license.licensed", False, False],
6673                             [self.plist[2], "license.licensed",
6674                             "license.licensed", True, False]]])
6675                 self.pkg("info licensed@1.3")
6676 
6677         def test_02_bug_7127117(self):
6678                 """Verifies that install with --parsable handles licenses
6679                 with non-ascii &amp; non UTF locale"""
6680                 self.image_create(self.rurl, prefix="bobcat")
6681 
6682                 self.pkg("install --parsable=0 nonascii@1.0")
6683                 self.pkg("install --parsable=0 utf8enc@1.0")
6684                 self.pkg("install --parsable=0 unsupported@1.0")
6685 
6686 
6687 class TestActionErrors(pkg5unittest.SingleDepotTestCase):
6688         """This set of tests is intended to verify that the client will handle
6689         image state and action errors gracefully during install or uninstall
6690         operations.  Unlike the client API version of these tests, the CLI only
6691         needs to be tested for failure cases since it uses the client API."""
6692 
6693         # Teardown the test root every time.
6694         persistent_setup = False
6695 
6696         dir10 = """
6697             open dir@1.0,5.11-0
6698             add dir path=dir mode=755 owner=root group=bin
6699             close """
6700 
6701         dir11 = """
6702             open dir@1.1,5.11-0
6703             add dir path=dir mode=750 owner=root group=bin
6704             close """
6705 
6706         # Purposefully omits depend on dir@1.0.
6707         filesub10 = """
6708             open filesub@1.0,5.11-0
6709             add file tmp/file path=dir/file mode=755 owner=root group=bin
6710             close """
6711 
6712         filesub11 = """
6713             open filesub@1.1,5.11-0
6714             add file tmp/file path=dir/file mode=444 owner=root group=bin
6715             close """
6716 
6717         # Dependency providing file intentionally omitted.
6718         hardlink10 = """
6719             open hardlink@1.0,5.11-0
6720             add hardlink path=hardlink target=file
6721             close """
6722 
6723         # Empty packages suitable for corruption testing.
6724         foo10 = """
6725             open foo@1.0,5.11-0
6726             close """
6727 
6728         unsupp10 = """
6729             open unsupported@1.0
6730             add depend type=require fmri=foo@1.0
6731             close """
6732 
6733         misc_files = ["tmp/file"]
6734 
6735         def setUp(self):
6736                 pkg5unittest.SingleDepotTestCase.setUp(self)
6737                 self.make_misc_files(self.misc_files)
6738 
6739                 plist = self.pkgsend_bulk(self.rurl, (self.dir10, self.dir11,
6740                     self.filesub10, self.filesub11, self.hardlink10))
6741 
6742                 self.plist = {}
6743                 for p in plist:
6744                         pfmri = fmri.PkgFmri(p, "5.11")
6745                         self.plist[pfmri.pkg_name] = pfmri
6746 
6747         @staticmethod
6748         def __write_empty_file(target, mode=644, owner="root", group="bin"):
6749                 f = open(target, "wb")
6750                 f.write("\n")
6751                 f.close()
6752                 os.chmod(target, mode)
6753                 owner = portable.get_user_by_name(owner, "/", True)
6754                 group = portable.get_group_by_name(group, "/", True)
6755                 os.chown(target, owner, group)
6756 
6757         def test_00_directory(self):
6758                 """Verify that directory install fails as expected when it has
6759                 been replaced with a link prior to install."""
6760 
6761                 self.image_create(self.rurl)
6762 
6763                 # The dest_dir's installed path.
6764                 dest_dir_name = "dir"
6765                 dest_dir = os.path.join(self.get_img_path(), dest_dir_name)
6766 
6767                 # Directory replaced with a link (fails for install).
6768                 self.__write_empty_file(dest_dir + ".src")
6769                 os.symlink(dest_dir + ".src", dest_dir)
6770                 self.pkg("install %s" % dest_dir_name, exit=1)
6771 
6772         def test_01_file(self):
6773                 """Verify that file install works as expected when its parent
6774                 directory has been replaced with a link."""
6775 
6776                 self.image_create(self.rurl)
6777 
6778                 # File's parent directory replaced with a link.
6779                 self.pkg("install dir")
6780                 src = os.path.join(self.get_img_path(), "dir")
6781                 os.mkdir(os.path.join(self.get_img_path(), "export"))
6782                 new_src = os.path.join(os.path.dirname(src), "export", "dir")
6783                 shutil.move(src, os.path.dirname(new_src))
6784                 os.symlink(new_src, src)
6785                 self.pkg("install filesub@1.0", exit=1)
6786 
6787         def test_02_hardlink(self):
6788                 """Verify that hardlink install fails as expected when
6789                 hardlink target is missing."""
6790 
6791                 self.image_create(self.rurl)
6792 
6793                 # Hard link target is missing (failure expected).
6794                 self.pkg("install hardlink", exit=1)
6795 
6796         def __populate_repo(self, unsupp_content=None):
6797                 # Publish a package and then add some unsupported action data
6798                 # to the repository's copy of the manifest and catalog.
6799                 sfmri = self.pkgsend_bulk(self.rurl, self.unsupp10)[0]
6800 
6801                 if unsupp_content is None:
6802                         # No manipulation required.
6803                         return
6804 
6805                 pfmri = fmri.PkgFmri(sfmri)
6806                 repo = self.get_repo(self.dcs[1].get_repodir())
6807                 mpath = repo.manifest(pfmri)
6808                 with open(mpath, "ab+") as mfile:
6809                         mfile.write(unsupp_content + "\n")
6810 
6811                 mcontent = None
6812                 with open(mpath, "rb") as mfile:
6813                         mcontent = mfile.read()
6814 
6815                 cat = repo.get_catalog("test")
6816                 cat.log_updates = False
6817 
6818                 # Update the catalog signature.
6819                 entry = cat.get_entry(pfmri)
6820                 entry["signature-sha-1"] = manifest.Manifest.hash_create(
6821                     mcontent)
6822 
6823                 # Update the catalog actions.
6824                 dpart = cat.get_part("catalog.dependency.C", must_exist=True)
6825                 entry = dpart.get_entry(pfmri)
6826                 entry["actions"].append(unsupp_content)
6827 
6828                 # Write out the new catalog.
6829                 cat.save()
6830 
6831         def test_03_unsupported(self):
6832                 """Verify that packages with invalid or unsupported actions are
6833                 handled gracefully.
6834                 """
6835 
6836                 # Base package needed for tests.
6837                 self.pkgsend_bulk(self.rurl, self.foo10)
6838 
6839                 # Verify that a package with unsupported content doesn't cause
6840                 # a problem.
6841                 newact = "depend type=new-type fmri=foo@1.1"
6842 
6843                 # Now create a new image and verify that pkg install will fail
6844                 # for the unsupported package, but succeed for the supported
6845                 # one.
6846                 self.__populate_repo(newact)
6847                 self.image_create(self.rurl)
6848                 self.pkg("install foo@1.0")
6849                 self.pkg("install unsupported@1.0", exit=1)
6850                 self.pkg("uninstall foo")
6851                 self.pkg("install foo@1.0 unsupported@1.0", exit=1)
6852 
6853                 # Verify that a package with invalid content behaves the same.
6854                 newact = "depend notvalid"
6855                 self.__populate_repo(newact)
6856                 self.pkg("refresh --full")
6857                 self.pkg("install foo@1.0")
6858                 self.pkg("install unsupported@1.0", exit=1)
6859                 self.pkg("uninstall foo")
6860 
6861                 # Now verify that if a newer version of the unsupported package
6862                 # is found that is supported, it can be installed.
6863                 self.__populate_repo()
6864                 self.pkg("refresh --full")
6865                 self.pkg("install foo@1.0 unsupported@1.0")
6866                 self.pkg("uninstall foo unsupported")
6867 
6868         def test_04_loop(self):
6869                 """Verify that if a directory or file is replaced with a link
6870                 that targets itself (resulting in ELOOP) pkg fails gracefully.
6871                 """
6872 
6873                 # Create an image and install a package delivering a file.
6874                 self.image_create(self.rurl)
6875                 self.pkg("install dir@1.0 filesub@1.0")
6876 
6877                 # Now replace the file with a link that points to itself.
6878                 def create_link_loop(fpath):
6879                         if os.path.isfile(fpath):
6880                                 portable.remove(fpath)
6881                         else:
6882                                 shutil.rmtree(fpath)
6883                         cwd = os.getcwd()
6884                         os.chdir(os.path.dirname(fpath))
6885                         os.symlink(os.path.basename(fpath),
6886                             os.path.basename(fpath))
6887                         os.chdir(cwd)
6888 
6889                 fpath = self.get_img_file_path("dir/file")
6890                 create_link_loop(fpath)
6891 
6892                 # Verify that pkg verify gracefully fails if traversing a
6893                 # link targeting itself.
6894                 self.pkg("verify", exit=1)
6895 
6896                 # Verify that pkg succeeds if attempting to update a
6897                 # package containing a file replaced with a link loop.
6898                 self.pkg("update filesub")
6899                 self.pkg("verify")
6900 
6901                 # Now remove the package delivering the file and replace the
6902                 # directory with a link loop.
6903                 self.pkg("uninstall filesub")
6904                 fpath = self.get_img_file_path("dir")
6905                 create_link_loop(fpath)
6906 
6907                 # Verify that pkg verify gracefully fails if traversing a
6908                 # link targeting itself.
6909                 self.pkg("verify", exit=1)
6910 
6911                 # Verify that pkg gracefully fails if attempting to update
6912                 # a package containing a directory replace with a link loop.
6913                 self.pkg("update", exit=1)
6914 
6915 
6916 class TestConflictingActions(pkg5unittest.SingleDepotTestCase):
6917         """This set of tests verifies that packages which deliver conflicting
6918         actions into the same name in a namespace cannot be installed
6919         simultaneously."""
6920 
6921         pkg_dupfiles = """
6922             open dupfiles@0,5.11-0
6923             add file tmp/file1 path=dir/pathname mode=0755 owner=root group=bin
6924             add file tmp/file2 path=dir/pathname mode=0755 owner=root group=bin
6925             close
6926         """
6927 
6928         pkg_dupfilesp1 = """
6929             open dupfilesp1@0,5.11-0
6930             add file tmp/file1 path=dir/pathname mode=0755 owner=root group=bin
6931             close
6932         """
6933 
6934         pkg_dupfilesp2 = """
6935             open dupfilesp2@0,5.11-0
6936             add file tmp/file2 path=dir/pathname mode=0755 owner=root group=bin
6937             close
6938         """
6939 
6940         pkg_dupfilesp2v2 = """
6941             open dupfilesp2@2,5.11-0
6942             close
6943         """
6944 
6945         pkg_dupfilesp3 = """
6946             open dupfilesp3@0,5.11-0
6947             add file tmp/file2 path=dir/pathname mode=0755 owner=root group=bin
6948             close
6949         """
6950 
6951         pkg_dupfilesp4 = """
6952             open dupfilesp4@0,5.11-0
6953             add file tmp/file3 path=dir/pathname mode=0755 owner=root group=bin
6954             close
6955         """
6956 
6957         pkg_dupotherfilesp1 = """
6958             open dupotherfilesp1@0,5.11-0
6959             add file tmp/file1 path=dir/namepath mode=0755 owner=root group=bin
6960             close
6961         """
6962 
6963         pkg_dupotherfilesp2 = """
6964             open dupotherfilesp2@0,5.11-0
6965             add file tmp/file2 path=dir/namepath mode=0755 owner=root group=bin
6966             close
6967         """
6968 
6969         pkg_dupotherfilesp2v2 = """
6970             open dupotherfilesp2@2,5.11-0
6971             close
6972         """
6973 
6974         pkg_dupotherfilesp3 = """
6975             open dupotherfilesp3@0,5.11-0
6976             add file tmp/file3 path=dir/namepath mode=0755 owner=root group=bin
6977             close
6978         """
6979 
6980         pkg_identicalfiles = """
6981             open identicalfiles@0,5.11-0
6982             add file tmp/file1 path=dir/pathname mode=0755 owner=root group=bin
6983             add file tmp/file1 path=dir/pathname mode=0755 owner=root group=bin
6984             close
6985         """
6986 
6987         pkg_overlaid = """
6988             open overlaid@0,5.11-0
6989             add file tmp/file1 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=allow
6990             close
6991         """
6992 
6993         # 'overlay' is ignored unless 'preserve' is also set.
6994         pkg_invalid_overlaid = """
6995             open invalid-overlaid@0,5.11-0
6996             add file tmp/file1 path=etc/pam.conf mode=644 owner=root group=sys overlay=allow
6997             close
6998         """
6999 
7000         pkg_overlayer = """
7001             open overlayer@0,5.11-0
7002             add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=true
7003             close
7004         """
7005 
7006         pkg_multi_overlayer = """
7007             open multi-overlayer@0,5.11-0
7008             add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys preserve=true overlay=true
7009             close
7010         """
7011 
7012         # overlaying file is treated as conflicting file if its mode, owner, and
7013         # group attributes don't match the action being overlaid
7014         pkg_mismatch_overlayer = """
7015             open mismatch-overlayer@0,5.11-0
7016             add file tmp/file2 path=etc/pam.conf mode=640 owner=root group=bin preserve=true overlay=true
7017             close
7018         """
7019 
7020         # overlaying file is treated as conflicting file if it doesn't set overlay=true
7021         # even if file being overlaid allows overlay.
7022         pkg_invalid_overlayer = """
7023             open invalid-overlayer@0,5.11-0
7024             add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys preserve=true
7025             close
7026         """
7027 
7028         pkg_unpreserved_overlayer = """
7029             open unpreserved-overlayer@0,5.11-0
7030             add file tmp/file2 path=etc/pam.conf mode=644 owner=root group=sys overlay=true
7031             close
7032         """
7033 
7034         pkgremote_pkg1 = """
7035             open pkg1@0,5.11-0
7036             add file tmp/file1 path=remote mode=644 owner=root group=sys
7037             close
7038         """
7039 
7040         pkgremote_pkg2 = """
7041             open pkg2@0,5.11-0
7042             add file tmp/file2 path=remote mode=644 owner=root group=sys
7043             close
7044         """
7045 
7046         pkg_dupfilesv1 = """
7047             open dupfilesv1@0,5.11-0
7048             add set name=variant.arch value=sparc value=i386
7049             add dir path=dir/pathname mode=0755 owner=root group=bin variant.arch=i386
7050             close
7051         """
7052 
7053         pkg_dupfilesv2 = """
7054             open dupfilesv2@0,5.11-0
7055             add dir path=dir/pathname mode=0755 owner=root group=bin
7056             close
7057         """
7058 
7059         pkg_dupfilesv3 = """
7060             open dupfilesv3@0,5.11-0
7061             add set name=variant.arch value=sparc value=i386
7062             add dir path=dir/pathname mode=0777 owner=root group=bin variant.arch=sparc
7063             close
7064         """
7065 
7066         pkg_dupfilesv4 = """
7067             open dupfilesv4@0,5.11-0
7068             add set name=variant.arch value=sparc value=i386
7069             add file tmp/file1 path=dir/pathname mode=0777 owner=root group=bin variant.arch=sparc
7070             add file tmp/file2 path=dir/pathname mode=0777 owner=root group=bin variant.arch=sparc
7071             add file tmp/file3 path=dir/pathname mode=0777 owner=root group=bin variant.arch=i386
7072             close
7073         """
7074 
7075         pkg_dupfilesv5 = """
7076             open dupfilesv5@0,5.11-0
7077             add set name=variant.opensolaris.zone value=global value=nonglobal
7078             add file tmp/file1 path=dir/pathname mode=0777 owner=root group=bin variant.opensolaris.zone=nonglobal
7079             close
7080         """
7081 
7082         pkg_dupfilesv6 = """
7083             open dupfilesv6@0,5.11-0
7084             add file tmp/file2 path=dir/pathname mode=0755 owner=root group=bin
7085             close
7086         """
7087 
7088         pkg_dupfilesf1 = """
7089             open dupfilesf1@0,5.11-0
7090             add dir path=dir/pathname mode=0755 owner=root group=bin facet.devel=true
7091             close
7092         """
7093 
7094         pkg_dupfilesf2 = """
7095             open dupfilesf2@0,5.11-0
7096             add dir path=dir/pathname mode=0755 owner=root group=bin facet.devel=false
7097             close
7098         """
7099 
7100         pkg_dupfilesf3 = """
7101             open dupfilesf3@0,5.11-0
7102             add dir path=dir/pathname mode=0755 owner=root group=bin
7103             close
7104         """
7105 
7106         pkg_dupfilesf4 = """
7107             open dupfilesf4@0,5.11-0
7108             add file tmp/file1 path=dir/pumpkin mode=0755 owner=root group=bin
7109             add file tmp/file2 path=dir/pumpkin mode=0755 owner=root group=bin facet.devel=true
7110             close
7111         """
7112 
7113         pkg_duppathfilelink = """
7114             open duppath-filelink@0,5.11-0
7115             add file tmp/file1 path=dir/pathname mode=0755 owner=root group=bin
7116             add link path=dir/pathname target=dir/other
7117             close
7118         """
7119 
7120         pkg_duplink = """
7121             open duplink@0,5.11-0
7122             add link path=dir/pathname target=dir/other
7123             close
7124         """
7125 
7126         pkg_dupmultitypes1 = """
7127             open dupmultitypes@1,5.11-0
7128             add link path=multitypepath target=dir/other
7129             add file tmp/file1 path=multitypepath mode=0644 owner=root group=bin
7130             add dir path=multitypepath mode=0755 owner=root group=bin
7131             close
7132         """
7133 
7134         pkg_dupmultitypes2 = """
7135             open dupmultitypes@2,5.11-0
7136             add dir path=multitypepath mode=0755 owner=root group=bin
7137             close
7138         """
7139 
7140         pkg_dupmultitypes3_0 = """
7141             open dupmultitypes3@0,5.11-0
7142             add link path=multitypepath target=blah
7143             add link path=multitypepath target=blah
7144             close
7145         """
7146 
7147         pkg_dupmultitypes3_1 = """
7148             open dupmultitypes3@1,5.11-0
7149             add dir path=multitypepath mode=0755 owner=root group=bin
7150             add dir path=multitypepath mode=0755 owner=root group=bin
7151             close
7152         """
7153 
7154         pkg_duppathnonidenticallinks = """
7155             open duppath-nonidenticallinks@0,5.11-0
7156             add link path=dir/pathname target=dir/something
7157             add link path=dir/pathname target=dir/other
7158             close
7159         """
7160 
7161         pkg_duppathnonidenticallinksp1 = """
7162             open duppath-nonidenticallinksp1@0,5.11-0
7163             add link path=dir/pathname target=dir/something
7164             close
7165         """
7166 
7167         pkg_duppathnonidenticallinksp2 = """
7168             open duppath-nonidenticallinksp2@0,5.11-0
7169             add link path=dir/pathname target=dir/other
7170             close
7171         """
7172 
7173         pkg_duppathnonidenticallinksp2v1 = """
7174             open duppath-nonidenticallinksp2@1,5.11-0
7175             close
7176         """
7177 
7178         pkg_duppathnonidenticaldirs = """
7179             open duppath-nonidenticaldirs@0,5.11-0
7180             add dir path=dir/pathname owner=root group=root mode=0755
7181             add dir path=dir/pathname owner=root group=bin mode=0711
7182             close
7183         """
7184 
7185         pkg_duppathalmostidenticaldirs = """
7186             open duppath-almostidenticaldirs@0,5.11-0
7187             add dir path=dir/pathname owner=root group=root mode=0755
7188             add dir path=dir/pathname owner=root group=root mode=755
7189             close
7190         """
7191 
7192         pkg_implicitdirs = """
7193             open implicitdirs@0,5.11-0
7194             add file tmp/file1 path=usr/bin/something mode=0755 owner=root group=bin
7195             add file tmp/file2 path=usr/bin mode=0755 owner=root group=bin
7196             close
7197         """
7198 
7199         pkg_implicitdirs2 = """
7200             open implicitdirs2@0,5.11-0
7201             add file tmp/file1 path=usr/bin/something mode=0755 owner=root group=bin
7202             add dir path=usr/bin mode=0700 owner=root group=bin
7203             close
7204         """
7205 
7206         pkg_implicitdirs3 = """
7207             open implicitdirs3@0,5.11-0
7208             add file tmp/file1 path=usr/bin/other mode=0755 owner=root group=bin
7209             close
7210         """
7211 
7212         pkg_implicitdirs4 = """
7213             open implicitdirs4@0,5.11-0
7214             add file tmp/file1 path=usr/bin/something mode=0755 owner=root group=bin
7215         """
7216 
7217         pkg_implicitdirs5 = """
7218             open implicitdirs5@0,5.11-0
7219             add dir path=usr/bin mode=0755 owner=root group=sys
7220         """
7221 
7222         pkg_implicitdirs6 = """
7223             open implicitdirs6@0,5.11-0
7224             add dir path=usr/bin mode=0755 owner=root group=bin
7225         """
7226 
7227         pkg_implicitdirs7 = """
7228             open implicitdirs7@0,5.11-0
7229             add file tmp/file1 path=usr/bin mode=0755 owner=root group=bin
7230         """
7231 
7232         pkg_dupdir = """
7233             open dupdir@0,5.11-0
7234             add dir path=dir/pathname owner=root group=bin mode=0755
7235             close
7236         """
7237 
7238         pkg_dupdirv1 = """
7239             open dupdir@1,5.11-0
7240             close
7241         """
7242 
7243         pkg_dupdirnowhere = """
7244             open dupdirnowhere@0,5.11-0
7245             add dir path=dir/pathname owner=root group=bin mode=0755
7246             close
7247         """
7248 
7249         pkg_dupdirp1 = """
7250             open dupdirp1@1,5.11-0
7251             add dir path=dir owner=root group=bin mode=0755
7252             close
7253         """
7254 
7255         pkg_dupdirp2 = """
7256             open dupdirp2@1,5.11-0
7257             add dir path=dir owner=root group=sys mode=0755
7258             close
7259         """
7260 
7261         pkg_dupdirp2_2 = """
7262             open dupdirp2@2,5.11-0
7263             add dir path=dir owner=root group=bin mode=0755
7264             close
7265         """
7266 
7267         pkg_dupdirp3 = """
7268             open dupdirp3@1,5.11-0
7269             add dir path=dir owner=root group=bin mode=0750
7270             close
7271         """
7272 
7273         pkg_dupdirp4 = """
7274             open dupdirp4@1,5.11-0
7275             add dir path=dir owner=root group=sys mode=0750
7276             close
7277         """
7278 
7279         pkg_dupdirp5 = """
7280             open dupdirp5@1,5.11-0
7281             add dir path=dir owner=root group=other mode=0755
7282             close
7283         """
7284 
7285         pkg_dupdirp6 = """
7286             open dupdirp6@1,5.11-0
7287             add dir path=dir owner=root group=other mode=0755
7288             close
7289         """
7290 
7291         pkg_dupdirp7 = """
7292             open dupdirp7@1,5.11-0
7293             add file tmp/file1 path=dir/file owner=root group=other mode=0755
7294             close
7295         """
7296 
7297         pkg_dupdirp8 = """
7298             open dupdirp8@1,5.11-0
7299             add dir path=dir owner=root group=bin mode=0755
7300             close
7301         """
7302 
7303         pkg_dupdirp8_2 = """
7304             open dupdirp8@2,5.11-0
7305             add dir path=dir owner=root group=sys mode=0755
7306             close
7307         """
7308 
7309         pkg_dupdirp9 = """
7310             open dupdirp9@1,5.11-0
7311             add dir path=var owner=root group=other mode=0755
7312             add dir path=usr owner=root group=other mode=0755
7313             close
7314         """
7315 
7316         pkg_dupdirp10 = """
7317             open dupdirp10@1,5.11-0
7318             add dir path=var owner=root group=bin mode=0755
7319             add dir path=usr owner=root group=bin mode=0755
7320             close
7321         """
7322 
7323         pkg_dupdirp11 = """
7324             open dupdirp11@1,5.11-0
7325             add dir path=usr/bin owner=root group=bin mode=0755
7326             add dir path=var/zap owner=root group=bin mode=0755
7327             close
7328         """
7329 
7330         pkg_dupdirp12 = """
7331             open dupdirp12@1,5.11-0
7332             add dir path=usr/bin owner=root group=bin mode=0755
7333             add legacy pkg=dupdirp9
7334             close
7335         """
7336 
7337         pkg_userdb = """
7338             open userdb@0,5.11-0
7339             add file tmp/passwd mode=0644 owner=root group=bin path=etc/passwd preserve=true
7340             add file tmp/group mode=0644 owner=root group=bin path=etc/group preserve=true
7341             add file tmp/shadow mode=0600 owner=root group=bin path=etc/shadow preserve=true
7342             add file tmp/ftpusers mode=0644 owner=root group=bin path=etc/ftpd/ftpusers preserve=true
7343             close
7344         """
7345 
7346         userdb_files = {
7347             "tmp/passwd": """\
7348 root:x:0:0::/root:/usr/bin/bash
7349 daemon:x:1:1::/:
7350 bin:x:2:2::/usr/bin:
7351 sys:x:3:3::/:
7352 adm:x:4:4:Admin:/var/adm:
7353 """,
7354             "tmp/group": """\
7355 root::0:
7356 other::1:root
7357 bin::2:root,daemon
7358 sys::3:root,bin,adm
7359 adm::4:root,daemon
7360 """,
7361             "tmp/shadow": """\
7362 root:9EIfTNBp9elws:13817::::::
7363 daemon:NP:6445::::::
7364 bin:NP:6445::::::
7365 sys:NP:6445::::::
7366 adm:NP:6445::::::
7367 """,
7368             "tmp/ftpusers": """\
7369 root
7370 bin
7371 sys
7372 adm
7373 """
7374         }
7375 
7376         pkg_dupuser = """
7377             open dupuser@0,5.11-0
7378             add user username=kermit group=adm gcos-field="kermit 1"
7379             add user username=kermit group=adm gcos-field="kermit 2"
7380             close
7381         """
7382 
7383         pkg_dupuserp1 = """
7384             open dupuserp1@0,5.11-0
7385             add user username=kermit group=adm gcos-field="kermit 1"
7386             close
7387         """
7388 
7389         pkg_dupuserp2 = """
7390             open dupuserp2@0,5.11-0
7391             add user username=kermit group=adm gcos-field="kermit 2"
7392             close
7393         """
7394 
7395         pkg_dupuserp2v2 = """
7396             open dupuserp2@1,5.11-0
7397             close
7398         """
7399 
7400         pkg_dupuserp3 = """
7401             open dupuserp3@0,5.11-0
7402             add user username=kermit group=adm gcos-field="kermit 2"
7403             close
7404         """
7405 
7406         pkg_dupuserp4 = """
7407             open dupuserp4@0,5.11-0
7408             add user username=kermit group=adm gcos-field="kermit 4"
7409             close
7410         """
7411 
7412         pkg_otheruser = """
7413             open otheruser@0,5.11-0
7414             add user username=fozzie group=adm home-dir=/export/home/fozzie
7415             close
7416         """
7417 
7418         pkg_othergroup = """
7419             open othergroup@0,5.11-0
7420             add group groupname=fozzie gid=87
7421             add group groupname=fozzie gid=88
7422             add group groupname=fozzie gid=89
7423             close
7424         """
7425 
7426         pkg_othergroup1 = """
7427             open othergroup@1,5.11-0
7428             add group groupname=fozzie gid=87
7429             close
7430         """
7431 
7432         pkg_driverdb = """
7433             open driverdb@0,5.11-0
7434             add file tmp/devlink.tab path=etc/devlink.tab mode=0644 owner=root group=bin
7435             add file tmp/driver_aliases path=etc/driver_aliases mode=0644 owner=root group=bin
7436             add file tmp/driver_classes path=etc/driver_classes mode=0644 owner=root group=bin
7437             add file tmp/minor_perm path=etc/minor_perm mode=0644 owner=root group=bin
7438             add file tmp/name_to_major path=etc/name_to_major mode=0644 owner=root group=bin
7439             add file tmp/device_policy path=etc/security/device_policy mode=0644 owner=root group=bin
7440             add file tmp/extra_privs path=etc/security/extra_privs mode=0644 owner=root group=bin
7441             close
7442         """
7443 
7444         driverdb_files = {
7445             "tmp/devlink.tab": "",
7446             "tmp/driver_aliases": "",
7447             "tmp/driver_classes": "",
7448             "tmp/minor_perm": "",
7449             "tmp/name_to_major": "",
7450             "tmp/device_policy": "",
7451             "tmp/extra_privs": ""
7452         }
7453 
7454         pkg_dupdrv = """
7455             open dupdriver@0,5.11-0
7456             add driver name=asy perms="* 0666 root sys" perms="*,cu 0600 uucp uucp"
7457             add driver name=asy perms="* 0666 root sys" alias=pci11c1,480
7458             close
7459         """
7460 
7461         pkg_dupdepend1 = """
7462             open dupdepend1@0,5.11-0
7463             add depend type=require fmri=dupfilesp1
7464             add depend type=require fmri=dupfilesp1
7465             close
7466         """
7467 
7468         pkg_dupdepend2 = """
7469             open dupdepend2@0,5.11-0
7470             add depend type=require fmri=dupfilesp1
7471             add depend type=incorporate fmri=dupfilesp1
7472             close
7473         """
7474 
7475         pkg_dupdepend3 = """
7476             open dupdepend3@0,5.11-0
7477             add depend type=require fmri=dupfilesp1@0-0
7478             add depend type=require fmri=dupfilesp1@0-0
7479             close
7480         """
7481 
7482         pkg_dupdepend4 = """
7483             open dupdepend4@0,5.11-0
7484             add depend type=require fmri=dupfilesp1@0-0
7485             add depend type=incorporate fmri=dupfilesp1@0-0
7486             close
7487         """
7488 
7489         pkg_tripledupfilea = """
7490             open tripledupfilea@0,5.11-0
7491             add set name=variant.foo value=one
7492             add file tmp/file1 path=file owner=root group=other mode=0755
7493             close
7494         """
7495 
7496         pkg_tripledupfileb = """
7497             open tripledupfileb@0,5.11-0
7498             add set name=variant.foo value=one value=two
7499             add file tmp/file2 path=file owner=root group=other mode=0755
7500             close
7501         """
7502 
7503         pkg_tripledupfilec = """
7504             open tripledupfilec@0,5.11-0
7505             add set name=variant.foo value=one value=two
7506             add file tmp/file3 path=file owner=root group=other mode=0755
7507             close
7508         """
7509 
7510         pkg_variantedtypes = """
7511             open vpath@0,5.11-0
7512             add set name=variant.foo value=one value=two
7513             add dir group=bin mode=0755 owner=root path=boot/platform \
7514                 variant.foo=two
7515             add link path=boot/platform target=../platform variant.foo=one
7516 
7517             close
7518         """
7519 
7520         misc_files = ["tmp/file1", "tmp/file2", "tmp/file3"]
7521 
7522         # Keep the depots around for the duration of the entire class
7523         persistent_setup = True
7524 
7525         def setUp(self):
7526                 pkg5unittest.SingleDepotTestCase.setUp(self)
7527                 self.make_misc_files(self.misc_files)
7528                 self.make_misc_files(self.userdb_files)
7529                 self.make_misc_files(self.driverdb_files)
7530 
7531                 pkgs = []
7532                 for objname in dir(self.__class__):
7533                         obj = getattr(self, objname)
7534                         if objname.startswith("pkg_") and type(obj) == str:
7535                                 pkgs.append(obj)
7536 
7537                 for i in xrange(20):
7538                         s = """
7539                                 open massivedupdir%d@0,5.11-0
7540                                 add dir path=usr owner=root group=%%s mode=%%s zig=%%s
7541                                 close
7542                         """ % i
7543 
7544                         if i == 14:
7545                                 s = s % ("root", "0750", "zag")
7546                         elif i in (1, 9):
7547                                 s = s % ("sys", "0750", "zag")
7548                         elif i in (3, 8, 12, 17):
7549                                 s = s % ("root", "0755", "zag")
7550                         else:
7551                                 s = s % ("sys", "0755", "zig")
7552 
7553                         pkgs.append(s)
7554 
7555                 self.pkgsend_bulk(self.rurl, pkgs)
7556 
7557         def test_multiple_files(self):
7558                 """Test the behavior of pkg(1) when multiple file actions
7559                 deliver to the same pathname."""
7560 
7561                 self.image_create(self.rurl)
7562 
7563                 # Duplicate files in the same package
7564                 self.pkg("install dupfiles", exit=1)
7565 
7566                 # Duplicate files in different packages, but in the same
7567                 # transaction
7568                 self.pkg("install dupfilesp1 dupfilesp2@0", exit=1)
7569 
7570                 # Duplicate files in different packages, in different
7571                 # transactions
7572                 self.pkg("install dupfilesp1")
7573                 self.pkg("install dupfilesp2@0", exit=1)
7574 
7575                 # Test that being in a duplicate file situation doesn't break
7576                 # you completely and allows you to add and remove other packages
7577                 self.pkg("-D broken-conflicting-action-handling=1 install dupfilesp2@0")
7578                 self.pkg("install implicitdirs2")
7579                 self.pkg("uninstall implicitdirs2")
7580 
7581                 # If the packages involved get upgraded but leave the actions
7582                 # themselves alone, we should be okay.
7583                 self.pkg("install dupfilesp2 dupfilesp3")
7584                 self.pkg("verify", exit=1)
7585 
7586                 # Test that removing one of two offending actions reverts the
7587                 # system to a clean state.
7588                 self.pkg("uninstall dupfilesp3")
7589                 self.pkg("verify")
7590 
7591                 # You should be able to upgrade to a fixed set of packages in
7592                 # order to move past the problem, too.
7593                 self.pkg("uninstall dupfilesp2")
7594                 self.pkg("-D broken-conflicting-action-handling=1 install dupfilesp2@0")
7595                 self.pkg("update")
7596                 self.pkg("verify")
7597 
7598                 # If we upgrade to a version of a conflicting package that no
7599                 # longer has the conflict, but at the same time introduce a new
7600                 # file action at the path with different contents, we should
7601                 # fail.
7602                 self.pkg("uninstall dupfilesp2")
7603                 self.pkg("-D broken-conflicting-action-handling=1 install dupfilesp2@0")
7604                 self.pkg("install dupfilesp2 dupfilesp4", exit=1)
7605 
7606                 # Removing one of more than two offending actions can't do much
7607                 # of anything, but should leave the system alone.
7608                 self.pkg("uninstall '*'")
7609                 self.pkg("-D broken-conflicting-action-handling=1 install "
7610                     "dupfilesp1 dupfilesp2@0 dupfilesp3")
7611                 # XXX The checks here rely on verify failing due to hashes being
7612                 # wrong; they should probably report a duplicate action instead.
7613                 self.pkg("verify", exit=1)
7614                 out1, err1 = self.output, self.errout
7615                 self.pkg("uninstall dupfilesp3")
7616                 # Because we removed dupfilesp3, the error output in this verify
7617                 # won't exactly match that from the previous one, but the one
7618                 # remaining failing package should give the same output since we
7619                 # didn't modify the FS, so search for the current output in the
7620                 # old.
7621                 self.pkg("verify", exit=1)
7622                 out2 = self.output
7623                 # Strip the first (header) line; this error might not have been
7624                 # first in the previous output.
7625                 out2 = out2[out2.index("\n") + 1:]
7626                 self.assert_(out2 in out1)
7627 
7628                 # Removing all but one of the offending actions should get us
7629                 # back to sanity.
7630                 self.pkg("uninstall '*'")
7631                 self.pkg("-D broken-conflicting-action-handling=1 install "
7632                     "dupfilesp1 dupfilesp2@0 dupfilesp3")
7633                 self.pkg("uninstall dupfilesp3 dupfilesp2")
7634                 self.pkg("verify")
7635 
7636                 # Make sure we handle cleaning up multiple files properly.
7637                 self.pkg("uninstall '*'")
7638                 self.pkg("-D broken-conflicting-action-handling=1 install "
7639                     "dupfilesp1 dupfilesp2@0 dupotherfilesp1 dupotherfilesp2")
7640                 self.pkg("uninstall dupfilesp2 dupotherfilesp2")
7641                 self.pkg("verify")
7642 
7643                 # Re-use the overlay packages for some preserve testing.
7644                 self.pkg("install overlaid")
7645                 self.pkg("-D broken-conflicting-action-handling=1 install "
7646                     "invalid-overlayer")
7647                 # We may have been able to lay down the package, but because the
7648                 # file is marked preserve=true, we didn't actually overwrite
7649                 self.file_contains("etc/pam.conf", "file2")
7650                 self.pkg("uninstall invalid-overlayer")
7651                 self.file_contains("etc/pam.conf", "file2")
7652 
7653                 # Make sure we get rid of all implicit directories.
7654                 self.pkg("uninstall '*'")
7655                 self.pkg("install implicitdirs3 implicitdirs4")
7656                 self.pkg("uninstall implicitdirs3 implicitdirs4")
7657 
7658                 if os.path.isdir(os.path.join(self.get_img_path(), "usr/bin")):
7659                         self.assert_(False, "Directory 'usr/bin' should not exist")
7660 
7661                 if os.path.isdir(os.path.join(self.get_img_path(), "usr")):
7662                         self.assert_(False, "Directory 'usr' should not exist")
7663 
7664                 # Make sure identical actions don't cause problems
7665                 self.pkg("install -nv identicalfiles", exit=1)
7666 
7667                 # Trigger a bug similar to 17943 via duplicate files.
7668                 self.pkg("publisher")
7669                 self.pkg("-D broken-conflicting-action-handling=1 install "
7670                     "dupfilesp1@0 dupfilesp2@0 dupfilesp3@0 dupotherfilesp1@0 "
7671                     "dupotherfilesp2@0 dupotherfilesp3@0")
7672                 self.pkg("update")
7673 
7674                 # If an uninstall causes a fixup to happen and we can't because
7675                 # we lost the cached files and the repo is down, make sure we
7676                 # fail before actually uninstalling anything.
7677                 self.dc.start()
7678                 self.pkgsend_bulk(self.durl, (self.pkgremote_pkg1,
7679                     self.pkgremote_pkg2))
7680                 self.image_create(self.durl)
7681                 self.pkg("install pkg1")
7682                 self.pkg("-D broken-conflicting-action-handling=1 install pkg2")
7683                 self.pkg("verify pkg2")
7684                 self.dc.stop()
7685                 self.pkg("uninstall pkg2", exit=1)
7686                 self.pkg("verify pkg2")
7687 
7688         def test_overlay_files(self):
7689                 """Test the behaviour of pkg(1) when actions for editable files
7690                 overlay other actions."""
7691 
7692                 # Ensure that overlay is allowed for file actions when one
7693                 # action has specified preserve attribute and overlay=allow,
7694                 # and *one* (only) other action has specified overlay=true
7695                 # (preserve does not have to be set).
7696                 self.image_create(self.rurl)
7697 
7698                 # Should fail because one action specified overlay=allow,
7699                 # but not preserve (it isn't editable).
7700                 self.pkg("install invalid-overlaid")
7701                 self.pkg("install overlayer", exit=1)
7702                 self.pkg("uninstall invalid-overlaid")
7703 
7704                 # Should fail because one action is overlayable but overlaying
7705                 # action doesn't declare its intent to overlay.
7706                 self.pkg("install overlaid")
7707                 self.file_contains("etc/pam.conf", "file1")
7708                 self.pkg("install invalid-overlayer", exit=1)
7709 
7710                 # Should fail because one action is overlayable but overlaying
7711                 # action mode, owner, and group attributes don't match.
7712                 self.pkg("install mismatch-overlayer", exit=1)
7713 
7714                 # Should succeed because one action is overlayable and
7715                 # overlaying action declares its intent to overlay.
7716                 self.pkg("contents -m overlaid")
7717                 self.pkg("contents -mr overlayer")
7718                 self.pkg("install overlayer")
7719                 self.file_contains("etc/pam.conf", "file2")
7720 
7721                 # Should fail because multiple actions are not allowed to
7722                 # overlay a single action.
7723                 self.pkg("install multi-overlayer", exit=1)
7724 
7725                 # Should succeed even though file is different than originally
7726                 # delivered since original package permits file modification.
7727                 self.pkg("verify overlaid overlayer")
7728 
7729                 # Should succeed because package delivering overlayable file
7730                 # permits modification and because package delivering overlay
7731                 # file permits modification.
7732                 self.file_append("etc/pam.conf", "zigit")
7733                 self.pkg("verify overlaid overlayer")
7734 
7735                 # Verify that the file isn't touched on uninstall of the
7736                 # overlaying package if package being overlaid is still
7737                 # installed.
7738                 self.pkg("uninstall overlayer")
7739                 self.file_contains("etc/pam.conf", "zigit")
7740                 self.file_contains("etc/pam.conf", "file2")
7741 
7742                 # Verify that removing the last package delivering an overlaid
7743                 # file removes the file.
7744                 self.pkg("uninstall overlaid")
7745                 self.file_doesnt_exist("etc/pam.conf")
7746 
7747                 # Verify that installing both packages at the same time results
7748                 # in only the overlaying file being delivered.
7749                 self.pkg("install overlaid overlayer")
7750                 self.file_contains("etc/pam.conf", "file2")
7751 
7752                 # Verify that the file isn't touched on uninstall of the
7753                 # overlaid package if overlaying package is still installed.
7754                 self.file_append("etc/pam.conf", "zigit")
7755                 self.pkg("uninstall overlaid")
7756                 self.file_contains("etc/pam.conf", "file2")
7757                 self.file_contains("etc/pam.conf", "zigit")
7758 
7759                 # Re-install overlaid package and verify that file content
7760                 # does not change.
7761                 self.pkg("install overlaid")
7762                 self.file_contains("etc/pam.conf", "file2")
7763                 self.file_contains("etc/pam.conf", "zigit")
7764                 self.pkg("uninstall overlaid overlayer")
7765 
7766                 # Should succeed because one action is overlayable and
7767                 # overlaying action declares its intent to overlay even
7768                 # though the overlaying action isn't marked with preserve.
7769                 self.pkg("install overlaid unpreserved-overlayer")
7770                 self.file_contains("etc/pam.conf", "file2")
7771 
7772                 # Should succeed because overlaid action permits modification
7773                 # and contents matches overlaying action.
7774                 self.pkg("verify overlaid unpreserved-overlayer")
7775 
7776                 # Should succeed even though file has been modified since
7777                 # overlaid action permits modification.
7778                 self.file_append("etc/pam.conf", "zigit")
7779                 self.pkg("verify overlaid")
7780 
7781                 # Should fail because overlaying action does not permit
7782                 # modification.
7783                 self.pkg("verify unpreserved-overlayer", exit=1)
7784 
7785                 # Should revert to content delivered by overlaying action.
7786                 self.pkg("fix unpreserved-overlayer")
7787                 self.file_contains("etc/pam.conf", "file2")
7788                 self.file_doesnt_contain("etc/pam.conf", "zigit")
7789 
7790                 # Should revert to content delivered by overlaying action.
7791                 self.file_append("etc/pam.conf", "zigit")
7792                 self.pkg("revert /etc/pam.conf")
7793                 self.file_contains("etc/pam.conf", "file2")
7794                 self.file_doesnt_contain("etc/pam.conf", "zigit")
7795                 self.pkg("uninstall unpreserved-overlayer")
7796 
7797                 # Should revert to content delivered by overlaid action.
7798                 self.file_contains("etc/pam.conf", "file2")
7799                 self.pkg("revert /etc/pam.conf")
7800                 self.file_contains("etc/pam.conf", "file1")
7801 
7802         def test_different_types(self):
7803                 """Test the behavior of pkg(1) when multiple actions of
7804                 different types deliver to the same pathname."""
7805 
7806                 self.image_create(self.rurl)
7807 
7808                 # In the same package
7809                 self.pkg("install duppath-filelink", exit=1)
7810 
7811                 # In different packages, in the same transaction
7812                 self.pkg("install dupfilesp1 duplink", exit=1)
7813 
7814                 # In different packages, in different transactions
7815                 self.pkg("install dupfilesp1")
7816                 self.pkg("install duplink", exit=1)
7817 
7818                 # Does removal of one of the busted packages get us out of the
7819                 # situation?
7820                 self.pkg("uninstall '*'")
7821                 self.pkg("-D broken-conflicting-action-handling=1 install dupfilesp1 duplink")
7822                 self.pkg("verify", exit=1)
7823                 self.pkg("uninstall dupfilesp1")
7824                 self.pkg("verify")
7825                 self.pkg("-D broken-conflicting-action-handling=1 install dupfilesp1")
7826                 self.pkg("uninstall duplink")
7827                 self.pkg("verify")
7828 
7829                 # Implicit directory conflicts with a file
7830                 self.pkg("uninstall '*'")
7831                 self.pkg("install implicitdirs", exit=1)
7832 
7833                 # Implicit directory coincides with a delivered directory
7834                 self.pkg("install implicitdirs2")
7835 
7836                 # Make sure that we don't die trying to fixup a directory using
7837                 # an implicit directory action.
7838                 self.pkg("uninstall '*'")
7839                 self.pkg("install implicitdirs4")
7840                 self.pkg("-D broken-conflicting-action-handling=1 install "
7841                     "implicitdirs7")
7842                 self.pkg("uninstall implicitdirs7")
7843                 # XXX We don't currently fix up anything beneath a directory
7844                 # that was restored, so we have to do it by hand.
7845                 os.mkdir("%s/usr/bin" % self.img_path())
7846                 shutil.copy("%s/tmp/file1" % self.test_root,
7847                     "%s/usr/bin/something" % self.img_path())
7848                 owner = portable.get_user_by_name("root", self.img_path(), True)
7849                 group = portable.get_group_by_name("bin", self.img_path(), True)
7850                 os.chown("%s/usr/bin/something" % self.img_path(), owner, group)
7851                 os.chmod("%s/usr/bin/something" % self.img_path(), 0755)
7852                 self.pkg("verify")
7853 
7854                 # Removing one of more than two offending actions can't do much
7855                 # of anything, but should leave the system alone.
7856                 self.pkg("uninstall '*'")
7857                 self.pkg("-D broken-conflicting-action-handling=1 install "
7858                     "dupfilesp1 duplink dupdir@0")
7859                 tmap = {
7860                     stat.S_IFIFO: "fifo",
7861                     stat.S_IFCHR: "character device",
7862                     stat.S_IFDIR: "directory",
7863                     stat.S_IFBLK: "block device",
7864                     stat.S_IFREG: "regular file",
7865                     stat.S_IFLNK: "symbolic link",
7866                     stat.S_IFSOCK: "socket",
7867                 }
7868                 thepath = "%s/dir/pathname" % self.img_path()
7869                 fmt = stat.S_IFMT(os.lstat(thepath).st_mode)
7870                 # XXX The checks here rely on verify failing due to action types
7871                 # not matching what's on the system; they should probably report
7872                 # duplicate actions instead.  Checking the output text is a bit
7873                 # ugly, too, but we do need to make sure that the two problems
7874                 # become one.
7875                 self.pkg("verify", exit=1)
7876                 verify_type_re = "File Type: '(.*?)' should be '(.*?)'"
7877                 matches = re.findall(verify_type_re, self.output)
7878                 # We make sure that what got reported is correct -- two actions
7879                 # of different types in conflict with whatever actually got laid
7880                 # down.
7881                 self.assert_(len(matches) == 2)
7882                 whatis = matches[0][0]
7883                 self.assert_(matches[1][0] == whatis)
7884                 self.assert_(whatis == tmap[fmt])
7885                 shouldbe = set(["symbolic link", "regular file", "directory"]) - \
7886                     set([whatis])
7887                 self.assert_(set([matches[0][1], matches[1][1]]) == shouldbe)
7888                 # Now we uninstall one of the packages delivering a type which
7889                 # isn't what's on the filesystem.  The filesystem should remain
7890                 # unchanged, but one of the errors should go away.
7891                 if whatis == "directory":
7892                         self.pkg("uninstall duplink")
7893                 else:
7894                         self.pkg("uninstall dupdir")
7895                 self.pkg("verify", exit=1)
7896                 matches = re.findall(verify_type_re, self.output)
7897                 self.assert_(len(matches) == 1)
7898                 nfmt = stat.S_IFMT(os.lstat(thepath).st_mode)
7899                 self.assert_(nfmt == fmt)
7900 
7901                 # Now we do the same thing, but we uninstall the package
7902                 # delivering the type which *is* what's on the filesystem.  This
7903                 # should also leave the filesystem alone, even though what's
7904                 # there will match *neither* of the remaining installed
7905                 # packages.
7906                 self.pkg("uninstall '*'")
7907                 self.pkg("-D broken-conflicting-action-handling=1 install "
7908                     "dupfilesp1 duplink dupdir@0")
7909                 fmt = stat.S_IFMT(os.lstat(thepath).st_mode)
7910                 self.pkg("verify", exit=1)
7911                 matches = re.findall(verify_type_re, self.output)
7912                 self.assert_(len(matches) == 2)
7913                 whatis = matches[0][0]
7914                 self.assert_(matches[1][0] == whatis)
7915                 self.assert_(whatis == tmap[fmt])
7916                 shouldbe = set(["symbolic link", "regular file", "directory"]) - \
7917                     set([whatis])
7918                 self.assert_(set([matches[0][1], matches[1][1]]) == shouldbe)
7919                 if whatis == "directory":
7920                         self.pkg("uninstall dupdir")
7921                 elif whatis == "symbolic link":
7922                         self.pkg("uninstall duplink")
7923                 elif whatis == "regular file":
7924                         self.pkg("uninstall dupfilesp1")
7925                 self.pkg("verify", exit=1)
7926                 matches = re.findall(verify_type_re, self.output)
7927                 self.assert_(len(matches) == 2)
7928                 nfmt = stat.S_IFMT(os.lstat(thepath).st_mode)
7929                 self.assert_(nfmt == fmt)
7930 
7931                 # Go from multiple conflicting types down to just one type.
7932                 # This also tests the case where a package version being newly
7933                 # installed gets fixed at the same time.
7934                 self.pkg("uninstall '*'")
7935                 self.pkg("-D broken-conflicting-action-handling=1 install "
7936                     "dupmultitypes@1")
7937                 self.pkg("install dupmultitypes")
7938                 self.pkg("verify")
7939 
7940                 # Upgrading from multiple instances of one refcounted type to
7941                 # multiple instances of another (here, link to directory) should
7942                 # succeed.
7943                 self.pkg("uninstall '*'")
7944                 self.pkg("install dupmultitypes3@0")
7945                 self.pkg("update")
7946 
7947         def test_conflicting_attrs_fs(self):
7948                 """Test the behavior of pkg(1) when multiple non-file actions of
7949                 the same type deliver to the same pathname, but whose other
7950                 attributes differ."""
7951 
7952                 self.image_create(self.rurl)
7953 
7954                 # One package, two links with different targets
7955                 self.pkg("install duppath-nonidenticallinks", exit=1)
7956 
7957                 # One package, two directories with different perms
7958                 self.pkg("install duppath-nonidenticaldirs", exit=1)
7959 
7960                 # One package, two dirs with same modes expressed two ways
7961                 self.pkg("install duppath-almostidenticaldirs")
7962 
7963                 # One package delivers a directory explicitly, another
7964                 # implicitly.
7965                 self.pkg("install implicitdirs2 implicitdirs3")
7966                 self.pkg("verify")
7967 
7968                 self.pkg("uninstall '*'")
7969 
7970                 # Make sure that we don't die trying to fixup a directory using
7971                 # an implicit directory action.
7972                 self.pkg("-D broken-conflicting-action-handling=1 install "
7973                     "implicitdirs4 implicitdirs5 implicitdirs6")
7974                 self.pkg("uninstall implicitdirs5")
7975                 self.pkg("verify")
7976 
7977                 self.pkg("uninstall '*'")
7978 
7979                 # Make sure that we don't die trying to fixup a directory using
7980                 # an implicit directory action when that's all that's left.
7981                 self.pkg("-D broken-conflicting-action-handling=1 install "
7982                     "implicitdirs4 implicitdirs5 implicitdirs6")
7983                 self.pkg("uninstall implicitdirs5 implicitdirs6")
7984                 self.pkg("verify")
7985 
7986                 self.pkg("uninstall '*'")
7987 
7988                 # If two packages deliver conflicting directories and another
7989                 # package delivers that directory implicitly, make sure the
7990                 # third package isn't blamed.
7991                 self.pkg("install implicitdirs4 implicitdirs5 implicitdirs6",
7992                     exit=1)
7993                 self.assert_("implicitdirs4" not in self.errout)
7994 
7995                 # Two packages, two links with different targets, installed at
7996                 # once
7997                 self.pkg("install duppath-nonidenticallinksp1 "
7998                     "duppath-nonidenticallinksp2@0", exit=1)
7999 
8000                 # Two packages, two links with different targets, installed
8001                 # separately
8002                 self.pkg("install duppath-nonidenticallinksp1")
8003                 self.pkg("install duppath-nonidenticallinksp2@0", exit=1)
8004 
8005                 self.pkg("uninstall '*'")
8006 
8007                 # If we get into a broken state, can we get out of it?
8008                 self.pkg("-D broken-conflicting-action-handling=1 install "
8009                     "duppath-nonidenticallinksp1 duppath-nonidenticallinksp2@0")
8010                 self.pkg("verify", exit=1)
8011                 self.pkg("install duppath-nonidenticallinksp2")
8012                 self.pkg("verify")
8013 
8014                 # If we get into a broken state, can we make it a little bit
8015                 # better by uninstalling one of the packages?  Removing dupdir5
8016                 # here won't reduce the number of different groups under which
8017                 # dir is delivered, but does reduce the number of actions
8018                 # delivering it.
8019                 self.pkg("uninstall '*'")
8020                 self.pkg("-D broken-conflicting-action-handling=1 install "
8021                     "dupdirp1 dupdirp2@1 dupdirp5 dupdirp6")
8022                 self.pkg("uninstall dupdirp5")
8023                 self.pkg("verify", exit=1)
8024 
8025                 self.pkg("-D broken-conflicting-action-handling=1 install "
8026                     "dupdirp5")
8027                 # Make sure we can install a package delivering an implicit
8028                 # directory that's currently in conflict.
8029                 self.pkg("install dupdirp7")
8030                 # And make sure we can uninstall it again.
8031                 self.pkg("uninstall dupdirp7")
8032 
8033                 # Removing the remaining conflicts in a couple of steps should
8034                 # result in a verifiable system.
8035                 self.pkg("uninstall dupdirp2")
8036                 self.pkg("uninstall dupdirp5 dupdirp6")
8037                 self.pkg("verify")
8038 
8039                 # Add everything back in, remove everything but one variant of
8040                 # the directory and an implicit directory, and verify.
8041                 self.pkg("-D broken-conflicting-action-handling=1 install "
8042                     "dupdirp2@1 dupdirp5 dupdirp6 dupdirp7")
8043                 self.pkg("uninstall dupdirp2 dupdirp5 dupdirp6")
8044                 self.pkg("verify")
8045 
8046                 # Get us into a saner state by upgrading.
8047                 self.pkg("-D broken-conflicting-action-handling=1 install "
8048                     "dupdirp2@1 dupdirp5 dupdirp6")
8049                 self.pkg("update dupdirp2@2")
8050 
8051                 # Get us into a sane state by upgrading.
8052                 self.pkg("uninstall dupdirp2 dupdirp5 dupdirp6")
8053                 self.pkg("-D broken-conflicting-action-handling=1 install "
8054                     "dupdirp2@1")
8055                 self.pkg("update dupdirp2@2")
8056                 self.pkg("verify")
8057 
8058                 # We start in a sane state, but the update would result in
8059                 # conflict, though no more actions deliver the path in
8060                 # question.
8061                 self.pkg("uninstall '*'")
8062                 self.pkg("install dupdirp1 dupdirp8@1")
8063                 self.pkg("update", exit=1)
8064 
8065                 # How about removing one of the conflicting packages?  We'll
8066                 # remove the package which doesn't match the state on disk.
8067                 self.pkg("uninstall '*'")
8068                 self.pkg("-D broken-conflicting-action-handling=1 install "
8069                     "duppath-nonidenticallinksp1 duppath-nonidenticallinksp2@0")
8070                 link = os.readlink("%s/dir/pathname" % self.img_path())
8071                 if link == "dir/something":
8072                         self.pkg("uninstall duppath-nonidenticallinksp2")
8073                 else:
8074                         self.pkg("uninstall duppath-nonidenticallinksp1")
8075                 self.pkg("verify")
8076 
8077                 # Now we'll try removing the package which *does* match the
8078                 # state on disk.  The code should clean up after us.
8079                 self.pkg("uninstall '*'")
8080                 self.pkg("-D broken-conflicting-action-handling=1 install "
8081                     "duppath-nonidenticallinksp1 duppath-nonidenticallinksp2@0")
8082                 link = os.readlink("%s/dir/pathname" % self.img_path())
8083                 if link == "dir/something":
8084                         self.pkg("uninstall duppath-nonidenticallinksp1")
8085                 else:
8086                         self.pkg("uninstall duppath-nonidenticallinksp2")
8087                 self.pkg("verify")
8088 
8089                 # Let's try a duplicate directory delivered with all sorts of
8090                 # crazy conflicts!
8091                 self.pkg("uninstall '*'")
8092                 self.pkg("install dupdirp1 dupdirp2@1 dupdirp3 dupdirp4", exit=1)
8093 
8094                 pkgs = " ".join("massivedupdir%d" % x for x in xrange(20))
8095                 self.pkg("install %s" % pkgs, exit=1)
8096 
8097                 # Trigger bug 17943: we install packages with conflicts in two
8098                 # directories (p9, p10).  We also install a package (p11) which
8099                 # delivers those directories implicitly.  Then remove the last,
8100                 # triggering the stack trace associated with the bug.
8101                 self.pkg("-D broken-conflicting-action-handling=1 install "
8102                     "dupdirp9 dupdirp10 dupdirp11")
8103                 self.pkg("uninstall dupdirp11")
8104 
8105                 # Do the same, but with a package that delivers var implicitly
8106                 # via a legacy action.
8107                 self.pkg("-D broken-conflicting-action-handling=1 install "
8108                     "dupdirp12")
8109                 self.pkg("uninstall dupdirp12")
8110 
8111         def test_conflicting_attrs_fs_varcets(self):
8112                 """Test the behavior of pkg(1) when multiple non-file actions of
8113                 the same type deliver to the same pathname, but differ in their
8114                 variants or facets."""
8115 
8116                 self.image_create(self.rurl)
8117 
8118                 # Two packages delivering the same directory, one under the
8119                 # current architecture, the other not tagged with an arch
8120                 # variant.
8121                 self.pkg("install dupfilesv1 dupfilesv2")
8122                 self.dir_exists("dir/pathname")
8123 
8124                 # Two packages delivering the same directory with different
8125                 # attributes -- one under the current architecture, the other
8126                 # tagged with another arch variant.
8127                 self.pkg("uninstall '*'")
8128                 self.pkg("install dupfilesv1 dupfilesv3")
8129                 if platform.processor() == "sparc":
8130                         self.dir_exists("dir/pathname", mode=0777)
8131                 else:
8132                         self.dir_exists("dir/pathname", mode=0755)
8133 
8134                 # Two packages delivering a file at the same path where one is
8135                 # tagged only for non-global zones should install successfully
8136                 # together in a global zone.
8137                 self.pkg("uninstall '*'")
8138                 self.pkg("install dupfilesv5 dupfilesv6")
8139                 path = os.path.join(self.get_img_path(), "dir/pathname")
8140                 try:
8141                         f = open(path)
8142                 except OSError, e:
8143                         if e.errno == errno.ENOENT:
8144                                 self.assert_(False, "File dir/pathname does not exist")
8145                         else:
8146                                 raise
8147                 self.assertEqual(f.read().rstrip(), "tmp/file2")
8148                 f.close()
8149 
8150                 # Two packages delivering the same directory, one with the
8151                 # devel facet false, the other true.
8152                 self.pkg("uninstall '*'")
8153                 self.pkg("install dupfilesf1 dupfilesf2")
8154                 self.dir_exists("dir/pathname")
8155 
8156                 # Two packages delivering the same directory, one with the
8157                 # devel facet true, the other without.
8158                 self.pkg("uninstall '*'")
8159                 self.pkg("install dupfilesf1 dupfilesf3")
8160                 self.dir_exists("dir/pathname")
8161 
8162                 # Two packages delivering the same directory, one with the
8163                 # devel facet false, the other without.
8164                 self.pkg("uninstall '*'")
8165                 self.pkg("install dupfilesf2 dupfilesf3")
8166                 self.dir_exists("dir/pathname")
8167 
8168         def test_conflicting_uninstall_publisher(self):
8169                 """Test the behaviour of pkg(1) when attempting to remove
8170                 conflicting packages from a publisher which has also been
8171                 removed."""
8172 
8173                 self.image_create(self.rurl)
8174                 # Dummy publisher so test publisher can be removed.
8175                 self.pkg("set-publisher -P ignored")
8176 
8177                 # If packages with conflicting actions are found during
8178                 # uninstall, and the publisher of the package has been
8179                 # removed, uninstall should still succeed.
8180                 self.pkg("-D broken-conflicting-action-handling=1 install "
8181                     "dupdirp1 dupdirp2@1")
8182                 self.pkg("unset-publisher test")
8183                 self.pkg("uninstall dupdirp2")
8184                 self.pkg("verify")
8185 
8186         def test_change_varcet(self):
8187                 """Test the behavior of pkg(1) when changing a variant or a
8188                 facet would cause the new image to contain conflicting
8189                 actions."""
8190 
8191                 # Create the image as an x86 image, as the first test only works
8192                 # changing variant from x86 to sparc.
8193                 self.image_create(self.rurl, variants={"variant.arch": "i386"})
8194 
8195                 # The x86 variant is safe, but the sparc variant has two files
8196                 # with the same pathname.
8197                 self.pkg("install dupfilesv4")
8198                 self.pkg("change-variant arch=sparc", exit=1)
8199 
8200                 # With the devel facet turned off, the package is safe, but
8201                 # turning it on would cause a duplicate file to be added.
8202                 self.pkg("change-facet devel=false")
8203                 self.pkg("install dupfilesf4")
8204                 self.pkg("change-facet devel=true", exit=1)
8205 
8206         def test_change_variant_removes_package(self):
8207                 """Test that a change-variant that removes a package and
8208                 improves but doesn't fix a conflicting action situation is
8209                 allowed."""
8210 
8211                 self.image_create(self.rurl, variants={"variant.foo": "one"})
8212                 self.pkg("install tripledupfileb")
8213                 self.pkg("-D broken-conflicting-action-handling=1 install "
8214                     "tripledupfilec")
8215                 self.pkg("-D broken-conflicting-action-handling=1 install "
8216                     "tripledupfilea")
8217                 self.pkg("change-variant variant.foo=two")
8218                 self.pkg("change-variant variant.foo=one", exit=1)
8219 
8220         def dir_exists(self, path, mode=None, owner=None, group=None):
8221                 dir_path = os.path.join(self.get_img_path(), path)
8222                 try:
8223                         st = os.stat(dir_path)
8224                 except OSError, e:
8225                         if e.errno == errno.ENOENT:
8226                                 self.assert_(False, "Directory %s does not exist" % path)
8227                         else:
8228                                 raise
8229                 if mode is not None:
8230                         self.assert_(stat.S_IMODE(st.st_mode) == mode)
8231                 if owner is not None:
8232                         self.assert_(st.st_uid == owner)
8233                 if group is not None:
8234                         self.assert_(st.st_gid == group)
8235 
8236         def test_multiple_users(self):
8237                 """Test the behavior of pkg(1) when multiple user actions
8238                 deliver the same user."""
8239 
8240                 # This is largely identical to test_multiple_files; we may want
8241                 # to commonize in the future.
8242 
8243                 self.image_create(self.rurl)
8244 
8245                 self.pkg("install userdb")
8246 
8247                 # Duplicate users in the same package
8248                 self.pkg("install dupuser", exit=1)
8249 
8250                 # Duplicate users in different packages, but in the same
8251                 # transaction
8252                 self.pkg("install dupuserp1 dupuserp2@0", exit=1)
8253 
8254                 # Duplicate users in different packages, in different
8255                 # transactions
8256                 self.pkg("install dupuserp1")
8257                 self.pkg("install dupuserp2@0", exit=1)
8258 
8259                 # Test that being in a duplicate user situation doesn't break
8260                 # you completely and allows you to add and remove other packages
8261                 self.pkg("-D broken-conflicting-action-handling=1 install "
8262                     "dupuserp2@0")
8263                 self.pkg("verify", exit=1)
8264                 self.pkg("install otheruser")
8265                 self.pkg("uninstall otheruser")
8266                 self.pkg("verify", exit=1)
8267 
8268                 # If the packages involved get upgraded but leave the actions
8269                 # themselves alone, we should be okay.
8270                 self.pkg("install dupuserp2 dupuserp3")
8271                 self.pkg("verify", exit=1)
8272 
8273                 # Test that removing one of two offending actions reverts the
8274                 # system to a clean state.
8275                 self.pkg("uninstall dupuserp3")
8276                 self.pkg("verify")
8277 
8278                 # You should be able to upgrade to a fixed set of packages in
8279                 # order to move past the problem, too.
8280                 self.pkg("uninstall dupuserp2")
8281                 self.pkg("-D broken-conflicting-action-handling=1 install "
8282                     "dupuserp2@0")
8283                 self.pkg("update")
8284                 self.pkg("verify")
8285 
8286                 # If we upgrade to a version of a conflicting package that no
8287                 # longer has the conflict, but at the same time introduce a new
8288                 # conflicting user action, we should fail.
8289                 self.pkg("uninstall dupuserp2")
8290                 self.pkg("-D broken-conflicting-action-handling=1 install "
8291                     "dupuserp2@0")
8292                 self.pkg("install dupuserp2 dupuserp4", exit=1)
8293 
8294                 # Removing one of more than two offending actions can't do much
8295                 # of anything, but should leave the system alone.
8296                 self.image_destroy()
8297                 self.image_create(self.rurl)
8298                 self.pkg("install userdb")
8299                 self.pkg("-D broken-conflicting-action-handling=1 install "
8300                     "dupuserp1 dupuserp2@0 dupuserp3")
8301                 self.pkg("verify", exit=1)
8302                 out1 = self.output
8303                 self.pkg("uninstall dupuserp3")
8304                 self.pkg("verify", exit=1)
8305                 out2 = self.output
8306                 out2 = out2[out2.index("\n") + 1:]
8307                 self.assert_(out2 in out1)
8308 
8309                 # Removing all but one of the offending actions should get us
8310                 # back to sanity.
8311                 self.image_destroy()
8312                 self.image_create(self.rurl)
8313                 self.pkg("install userdb")
8314                 self.pkg("-D broken-conflicting-action-handling=1 install "
8315                     "dupuserp1 dupuserp2@0 dupuserp3")
8316                 self.pkg("uninstall dupuserp3 dupuserp2")
8317                 self.pkg("verify")
8318 
8319                 # Make sure we don't get confused when two actions in different
8320                 # namespace groups but with the same key attribute value are
8321                 # adjacent in the action cache.
8322                 self.pkg("-D broken-conflicting-action-handling=1 install "
8323                     "otheruser othergroup@0")
8324                 self.pkg("update othergroup")
8325 
8326         def test_multiple_drivers(self):
8327                 """Test the behavior of pkg(1) when multiple driver actions
8328                 deliver the same driver."""
8329 
8330                 self.image_create(self.rurl)
8331 
8332                 self.pkg("install driverdb")
8333 
8334                 self.pkg("install dupdriver", exit=1)
8335 
8336         def test_multiple_depend(self):
8337                 """Test to make sure we can have multiple depend actions on
8338                 (more or less) the same fmri"""
8339 
8340                 self.image_create(self.rurl)
8341 
8342                 # Two identical unversioned require dependencies
8343                 self.pkg("install dupdepend1")
8344 
8345                 # Two dependencies of different types on an identical
8346                 # unversioned fmri
8347                 self.pkg("install dupdepend2")
8348 
8349                 # Two identical versioned require dependencies
8350                 self.pkg("install dupdepend3")
8351 
8352                 # Two dependencies of different types on an identical versioned
8353                 # fmri
8354                 self.pkg("install dupdepend4")
8355 
8356         def test_varianted_types(self):
8357                 """Test that actions which would otherwise conflict but are
8358                 delivered under different variants don't conflict."""
8359 
8360                 self.pkg_image_create(repourl=self.rurl,
8361                     additional_args="--variant foo=one")
8362                 self.pkg("install vpath")
8363 
8364 
8365 if __name__ == "__main__":
8366         unittest.main()
</pre></body></html>
 
 
Close
loading
Please Confirm
Close