Example #1
0
        def test(top_xml, diag_xml, expected_error):
            root = qdom.parse(
                BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{top}">
			  <name>Top-level</name>
			  <summary>Top-level</summary>
			  <group>
			    {top_xml}
			  </group>
			</interface>""".format(top=top_uri, top_xml=top_xml).encode("utf-8")))
            self.import_feed(top_uri, root)

            root = qdom.parse(
                BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{diag}">
			  <name>Diagnostics</name>
			  <summary>Diagnostics</summary>
			  <group>
			    {impls}
			  </group>
			</interface>""".format(diag=diag_uri, impls=diag_xml).encode("utf-8")))
            self.import_feed(diag_uri, root)

            root = qdom.parse(
                BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{old}">
			  <name>Old</name>
			  <summary>Old</summary>
			  <feed src='{diag}'/>
			  <replaced-by interface='{diag}'/>
			</interface>""".format(diag=diag_uri, old=old_uri).encode("utf-8")))
            self.import_feed(old_uri, root)

            r = Requirements(top_uri)
            r.os = "Windows"
            r.cpu = "x86_64"
            s = solver.DefaultSolver(self.config)
            s.solve_for(r)
            assert not s.ready, s.selections.selections

            if expected_error != str(s.get_failure_reason()):
                print(s.get_failure_reason())

            self.assertEqual(expected_error, str(s.get_failure_reason()))

            return s
		def test(top_xml, diag_xml, expected_error):
			root = qdom.parse(BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{top}">
			  <name>Top-level</name>
			  <summary>Top-level</summary>
			  <group>
			    {top_xml}
			  </group>
			</interface>""".format(top = top_uri, top_xml = top_xml).encode("utf-8")))
			self.import_feed(top_uri, root)

			root = qdom.parse(BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{diag}">
			  <name>Diagnostics</name>
			  <summary>Diagnostics</summary>
			  <group>
			    {impls}
			  </group>
			</interface>""".format(diag = diag_uri, impls = diag_xml).encode("utf-8")))
			self.import_feed(diag_uri, root)

			root = qdom.parse(BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{old}">
			  <name>Old</name>
			  <summary>Old</summary>
			  <feed src='{diag}'/>
			  <replaced-by interface='{diag}'/>
			</interface>""".format(diag = diag_uri, old = old_uri).encode("utf-8")))
			self.import_feed(old_uri, root)

			r = Requirements(top_uri)
			r.os = "Windows"
			r.cpu = "x86_64"
			s = solver.DefaultSolver(self.config)
			s.solve_for(r)
			assert not s.ready, s.selections.selections

			if expected_error != str(s.get_failure_reason()):
				print(s.get_failure_reason())

			self.assertEqual(expected_error, str(s.get_failure_reason()))

			return s
Example #3
0
    def testDiagnostics(self):
        top_uri = 'http://localhost/top.xml'
        old_uri = 'http://localhost/diagnostics-old.xml'
        diag_uri = 'http://localhost/diagnostics.xml'

        def test(top_xml, diag_xml, expected_error):
            root = qdom.parse(
                BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{top}">
			  <name>Top-level</name>
			  <summary>Top-level</summary>
			  <group>
			    {top_xml}
			  </group>
			</interface>""".format(top=top_uri, top_xml=top_xml).encode("utf-8")))
            self.import_feed(top_uri, root)

            root = qdom.parse(
                BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{diag}">
			  <name>Diagnostics</name>
			  <summary>Diagnostics</summary>
			  <group>
			    {impls}
			  </group>
			</interface>""".format(diag=diag_uri, impls=diag_xml).encode("utf-8")))
            self.import_feed(diag_uri, root)

            root = qdom.parse(
                BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{old}">
			  <name>Old</name>
			  <summary>Old</summary>
			  <feed src='{diag}'/>
			  <replaced-by interface='{diag}'/>
			</interface>""".format(diag=diag_uri, old=old_uri).encode("utf-8")))
            self.import_feed(old_uri, root)

            r = Requirements(top_uri)
            r.os = "Windows"
            r.cpu = "x86_64"
            s = solver.DefaultSolver(self.config)
            s.solve_for(r)
            assert not s.ready, s.selections.selections

            if expected_error != str(s.get_failure_reason()):
                print(s.get_failure_reason())

            self.assertEqual(expected_error, str(s.get_failure_reason()))

            return s

        # No implementations
        s = test(
            "", "", "Can't find all required implementations:\n" +
            "- http://localhost/top.xml -> (problem)\n" +
            "    No known implementations at all")

        # No retrieval method
        s = test(
            "<implementation version='1' id='1'><requires interface='{diag}'/></implementation>"
            .format(diag=diag_uri), "",
            "Can't find all required implementations:\n" +
            "- http://localhost/top.xml -> (problem)\n" +
            "    No usable implementations:\n" +
            "      1 (1): No retrieval methods")

        # No run command
        s = test(
            """<implementation version='1' id='1'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}'>
				  <version not-before='100'/>
				</requires>
			     </implementation>""".format(diag=diag_uri), "",
            "Can't find all required implementations:\n" +
            "- http://localhost/top.xml -> (problem)\n" +
            "    Rejected candidates:\n" + "      1: No run command")

        # Missing command from dependency
        s = test(
            """<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}'>
				  <binding command='foo'/>
				</requires>
			     </implementation>""".format(diag=diag_uri),
            """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>""", "Can't find all required implementations:\n" +
            "- http://localhost/diagnostics.xml -> (problem)\n" +
            "    http://localhost/top.xml 1 requires 'foo' command\n" +
            "    Rejected candidates:\n" + "      diag-5: No foo command\n" +
            "- http://localhost/top.xml -> 1 (1)")

        # Failing distribution requirement
        s = test(
            """<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}' distribution='foo'/>
			     </implementation>""".format(diag=diag_uri),
            """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    http://localhost/top.xml 1 requires distro foo\n"
            "    No usable implementations satisfy the restrictions:\n"
            "      diag-5 (5): incompatible with restrictions\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Failing version requirement on library
        s = test(
            """<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}' version='100..!200'/>
			     </implementation>""".format(diag=diag_uri),
            """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    http://localhost/top.xml 1 requires version 100..!200\n"
            "    No usable implementations satisfy the restrictions:\n"
            "      diag-5 (5): incompatible with restrictions\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Failing version requires on root
        s = test(
            """<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}'/>
			     </implementation>""".format(diag=diag_uri),
            """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
				<restricts interface='{top_uri}' version='100..!200'/>
			     </implementation>
			 """.format(top_uri=top_uri), "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    Rejected candidates:\n"
            "      diag-5: requires http://localhost/top.xml version 100..!200\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Parse error in version restriction
        logger.setLevel(logging.ERROR)
        s = test(
            """<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}' version='100..200'/>
			     </implementation>""".format(diag=diag_uri),
            """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    http://localhost/top.xml 1 requires <impossible: Can't parse version restriction '100..200': End of range must be exclusive (use '..!200', not '..200')>\n"
            "    No usable implementations satisfy the restrictions:\n"
            "      diag-5 (5): incompatible with restrictions\n"
            "- http://localhost/top.xml -> 1 (1)")
        logger.setLevel(logging.WARNING)

        # Old-style version restriction
        s = test(
            """<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}'>
				  <version not-before='100'/>
				</requires>
			     </implementation>""".format(diag=diag_uri),
            """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    http://localhost/top.xml 1 requires 100 <= version\n"
            "    No usable implementations satisfy the restrictions:\n"
            "      diag-5 (5): incompatible with restrictions\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Mismatched machine types
        s = test(
            """<group>
			      <requires interface='{diag}'/>
			      <implementation version='1' id='1' main='foo' arch='Windows-i486'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
			     </implementation>
			   </group>""".format(diag=diag_uri), """<group>
			      <implementation version='5' id='diag-5' arch='Windows-x86_64'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			   </group>
			 """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    Rejected candidates:\n"
            "      diag-5: Can't use x86_64 with selection of Top-level (i486)\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Only show the first five unusable reasons
        s = test(
            """<group>
			      <requires interface='{diag}'/>
			      <implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
			     </implementation>
			   </group>""".format(diag=diag_uri), """<group>
			      <implementation version='1' id='diag-1'/>
			      <implementation version='2' id='diag-2'/>
			      <implementation version='3' id='diag-3'/>
			      <implementation version='4' id='diag-4'/>
			      <implementation version='5' id='diag-5'/>
			      <implementation version='6' id='diag-6'/>
			   </group>
			 """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    No usable implementations:\n"
            "      diag-6 (6): No retrieval methods\n"
            "      diag-5 (5): No retrieval methods\n"
            "      diag-4 (4): No retrieval methods\n"
            "      diag-3 (3): No retrieval methods\n"
            "      diag-2 (2): No retrieval methods\n"
            "      ...\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Only show the first five rejection reasons
        s = test(
            """<group>
			      <requires interface='{diag}'>
			        <version before='6'/>
			      </requires>
			      <implementation version='1' id='1' main='foo' arch='Windows-i486'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
			     </implementation>
			   </group>""".format(diag=diag_uri), """<group>
			      <implementation version='5' id='diag-5' arch='Windows-x86_64'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			     <implementation version='6' id='diag-6' arch='Windows-i486'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			     {others}
			   </group>
			 """.format(others="\n".join(
                """<implementation version='{i}' id='diag-{i}' arch='Windows-x86_64'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>""".format(i=i) for i in range(0, 5))),
            "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    http://localhost/top.xml 1 requires version < 6\n"
            "    Rejected candidates:\n"
            "      diag-5: Can't use x86_64 with selection of Top-level (i486)\n"
            "      diag-4: Can't use x86_64 with selection of Top-level (i486)\n"
            "      diag-3: Can't use x86_64 with selection of Top-level (i486)\n"
            "      diag-2: Can't use x86_64 with selection of Top-level (i486)\n"
            "      diag-1: Can't use x86_64 with selection of Top-level (i486)\n"
            "      ...\n"
            "- http://localhost/top.xml -> 1 (1)")

        # Justify why a particular version can't be used
        iface = self.config.iface_cache.get_interface(diag_uri)
        impl = self.config.iface_cache.get_feed(
            diag_uri).implementations['diag-5']
        r = Requirements(top_uri)
        r.os = 'Windows'
        r.cpu = 'x86_64'
        self.assertEqual(
            "There is no possible selection using Diagnostics 5.\n"
            "Can't find all required implementations:\n"
            "- http://localhost/diagnostics.xml -> (problem)\n"
            "    http://localhost/top.xml 1 requires version < 6\n"
            "    User requested implementation 5 (diag-5)\n"
            "    Rejected candidates:\n"
            "      diag-5: Can't use x86_64 with selection of Top-level (i486)\n"
            "- http://localhost/top.xml -> 1 (1)",
            s.justify_decision(r, iface, impl))

        # Can't select old and diag because they conflict
        test(
            """<group>
			  <requires interface='{diag}'/>
			  <requires interface='{old}'/>
			  <implementation version='1' id='1' main='foo'>
			    <archive href='http://localhost:3000/foo.tgz' size='100'/>
			  </implementation>
		        </group>""".format(diag=diag_uri, old=old_uri), """<group>
			 <implementation version='5' id='diag-5'>
			   <archive href='http://localhost:3000/diag.tgz' size='100'/>
			 </implementation>
		       </group>
		    """, "Can't find all required implementations:\n"
            "- http://localhost/diagnostics-old.xml -> (problem)\n"
            "    Replaced by (and therefore conflicts with) http://localhost/diagnostics.xml\n"
            "    No usable implementations satisfy the restrictions:\n"
            "      diag-5 (5): incompatible with restrictions\n"
            "- http://localhost/diagnostics.xml -> 5 (diag-5)\n"
            "    Replaces (and therefore conflicts with) http://localhost/diagnostics-old.xml\n"
            "- http://localhost/top.xml -> 1 (1)")
Example #4
0
	def testDiagnostics(self):
		top_uri = 'http://localhost/top.xml'
		old_uri = 'http://localhost/diagnostics-old.xml'
		diag_uri = 'http://localhost/diagnostics.xml'

		def test(top_xml, diag_xml, expected_error):
			root = qdom.parse(BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{top}">
			  <name>Top-level</name>
			  <summary>Top-level</summary>
			  <group>
			    {top_xml}
			  </group>
			</interface>""".format(top = top_uri, top_xml = top_xml).encode("utf-8")))
			self.import_feed(top_uri, root)

			root = qdom.parse(BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{diag}">
			  <name>Diagnostics</name>
			  <summary>Diagnostics</summary>
			  <group>
			    {impls}
			  </group>
			</interface>""".format(diag = diag_uri, impls = diag_xml).encode("utf-8")))
			self.import_feed(diag_uri, root)

			root = qdom.parse(BytesIO("""<?xml version="1.0" ?>
			<interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface" uri="{old}">
			  <name>Old</name>
			  <summary>Old</summary>
			  <feed src='{diag}'/>
			  <replaced-by interface='{diag}'/>
			</interface>""".format(diag = diag_uri, old = old_uri).encode("utf-8")))
			self.import_feed(old_uri, root)

			r = Requirements(top_uri)
			r.os = "Windows"
			r.cpu = "x86_64"
			s = solver.DefaultSolver(self.config)
			s.solve_for(r)
			assert not s.ready, s.selections.selections

			self.assertEqual(expected_error, str(s.get_failure_reason()))

			return s

		s = test("", "",
			"Can't find all required implementations:\n" +
			"- http://localhost/top.xml -> (problem)\n" +
			"    No known implementations at all")

		s = test("<implementation version='1' id='1'><requires interface='{diag}'/></implementation>".format(diag = diag_uri),
			 "",
			 "Can't find all required implementations:\n" +
			 "- http://localhost/top.xml -> (problem)\n" +
			 "    No usable implementations:\n" +
			 "      1: No retrieval methods")

		s = test("""<implementation version='1' id='1'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}'>
				  <version not-before='100'/>
				</requires>
			     </implementation>""".format(diag = diag_uri),
			 "",
			 "Can't find all required implementations:\n" +
			 "- http://localhost/top.xml -> (problem)\n" +
			 "    Rejected candidates:\n" +
			 "      1: No run command")

		s = test("""<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}' version='100..!200'/>
			     </implementation>""".format(diag = diag_uri),
			 """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """,
			 "Can't find all required implementations:\n"
			 "- http://localhost/diagnostics.xml -> (problem)\n"
			 "    http://localhost/top.xml 1 requires version 100..!200\n"
			 "    No usable implementations satisfy the restrictions\n"
			 "- http://localhost/top.xml -> 1 (1)")

		logger.setLevel(logging.ERROR)
		s = test("""<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}' version='100..200'/>
			     </implementation>""".format(diag = diag_uri),
			 """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """,
			 "Can't find all required implementations:\n"
			 "- http://localhost/diagnostics.xml -> (problem)\n"
			 "    http://localhost/top.xml 1 requires <impossible: Can't parse version restriction '100..200': End of range must be exclusive (use '..!200', not '..200')>\n"
			 "    No usable implementations satisfy the restrictions\n"
			 "- http://localhost/top.xml -> 1 (1)")
		logger.setLevel(logging.WARNING)

		s = test("""<implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
				<requires interface='{diag}'>
				  <version not-before='100'/>
				</requires>
			     </implementation>""".format(diag = diag_uri),
			 """<implementation version='5' id='diag-5'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			 """,
			 "Can't find all required implementations:\n"
			 "- http://localhost/diagnostics.xml -> (problem)\n"
			 "    http://localhost/top.xml 1 requires 100 <= version\n"
			 "    No usable implementations satisfy the restrictions\n"
			 "- http://localhost/top.xml -> 1 (1)")

		s = test("""<group>
			      <requires interface='{diag}'/>
			      <implementation version='1' id='1' main='foo' arch='Windows-i486'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
			     </implementation>
			   </group>""".format(diag = diag_uri),
			 """<group>
			      <implementation version='5' id='diag-5' arch='Windows-x86_64'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			   </group>
			 """,
			 "Can't find all required implementations:\n"
			 "- http://localhost/diagnostics.xml -> (problem)\n"
			 "    Rejected candidates:\n"
			 "      diag-5: Can't use x86_64 with selection of Top-level (i486)\n"
			 "- http://localhost/top.xml -> 1 (1)")

		s = test("""<group>
			      <requires interface='{diag}'/>
			      <implementation version='1' id='1' main='foo'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
			     </implementation>
			   </group>""".format(diag = diag_uri),
			 """<group>
			      <implementation version='1' id='diag-1'/>
			      <implementation version='2' id='diag-2'/>
			      <implementation version='3' id='diag-3'/>
			      <implementation version='4' id='diag-4'/>
			      <implementation version='5' id='diag-5'/>
			      <implementation version='6' id='diag-6'/>
			   </group>
			 """,
			 "Can't find all required implementations:\n"
			 "- http://localhost/diagnostics.xml -> (problem)\n"
			 "    No usable implementations:\n"
			 "      diag-6: No retrieval methods\n"
			 "      diag-5: No retrieval methods\n"
			 "      diag-4: No retrieval methods\n"
			 "      diag-3: No retrieval methods\n"
			 "      diag-2: No retrieval methods\n"
			 "      ...\n"
			 "- http://localhost/top.xml -> 1 (1)")

		s = test("""<group>
			      <requires interface='{diag}'>
			        <version before='6'/>
			      </requires>
			      <implementation version='1' id='1' main='foo' arch='Windows-i486'>
				<archive href='http://localhost:3000/foo.tgz' size='100'/>
			     </implementation>
			   </group>""".format(diag = diag_uri),
			 """<group>
			      <implementation version='5' id='diag-5' arch='Windows-x86_64'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			     <implementation version='6' id='diag-6' arch='Windows-i486'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>
			     {others}
			   </group>
			 """.format(others = "\n".join(
			  """<implementation version='{i}' id='diag-{i}' arch='Windows-x86_64'>
				<archive href='http://localhost:3000/diag.tgz' size='100'/>
			     </implementation>""".format(i = i) for i in range(0, 5))),
			 "Can't find all required implementations:\n"
			 "- http://localhost/diagnostics.xml -> (problem)\n"
			 "    http://localhost/top.xml 1 requires version < 6\n"
			 "    Rejected candidates:\n"
			 "      diag-5: Can't use x86_64 with selection of Top-level (i486)\n"
			 "      diag-4: Can't use x86_64 with selection of Top-level (i486)\n"
			 "      diag-3: Can't use x86_64 with selection of Top-level (i486)\n"
			 "      diag-2: Can't use x86_64 with selection of Top-level (i486)\n"
			 "      diag-1: Can't use x86_64 with selection of Top-level (i486)\n"
			 "      ...\n"
			 "- http://localhost/top.xml -> 1 (1)")

		iface = self.config.iface_cache.get_interface(diag_uri)
		impl = self.config.iface_cache.get_feed(diag_uri).implementations['diag-5']
		r = Requirements(top_uri)
		r.os = 'Windows'
		self.assertEqual("There is no possible selection using Diagnostics 5.\n"
				 "Can't find all required implementations:\n"
				 "- http://localhost/diagnostics.xml -> (problem)\n"
				 "    http://localhost/top.xml 1 requires version < 6\n"
				 "    User requested implementation 5 (diag-5)\n"
				 "    Rejected candidates:\n"
				 "      diag-5: Can't use x86_64 with selection of Top-level (i486)\n"
				 "- http://localhost/top.xml -> 1 (1)",
				s.justify_decision(r, iface, impl))

		# Can't select old and diag because they conflict
		test("""<group>
			  <requires interface='{diag}'/>
			  <requires interface='{old}'/>
			  <implementation version='1' id='1' main='foo'>
			    <archive href='http://localhost:3000/foo.tgz' size='100'/>
			  </implementation>
		        </group>""".format(diag = diag_uri, old = old_uri),
		    """<group>
			 <implementation version='5' id='diag-5'>
			   <archive href='http://localhost:3000/diag.tgz' size='100'/>
			 </implementation>
		       </group>
		    """,
		    "Can't find all required implementations:\n"
		    "- http://localhost/diagnostics-old.xml -> (problem)\n"
		    "    Replaced by (and therefore conflicts with) http://localhost/diagnostics.xml\n"
		    "    No usable implementations satisfy the restrictions\n"
		    "- http://localhost/diagnostics.xml -> 5 (diag-5)\n"
		    "    Replaces (and therefore conflicts with) http://localhost/diagnostics-old.xml\n"
		    "- http://localhost/top.xml -> 1 (1)")