@@ -142,7 +142,9 @@ def test_keywordreq(self, repo):
142142def mk_graph (repo , category = BugCategory .STABLEREQ ):
143143 # build a DependencyGraph without running its heavy __init__
144144 graph = bugs .DependencyGraph .__new__ (bugs .DependencyGraph )
145- graph .options = SimpleNamespace (repo = repo , search_repo = repo , category = category )
145+ graph .options = SimpleNamespace (
146+ repo = repo , search_repo = repo , category = category , filter_stablereqs = False
147+ )
146148 graph .out = SimpleNamespace (
147149 write = lambda * a , ** k : None , warn = lambda * a , ** k : None , flush = lambda : None
148150 )
@@ -151,6 +153,8 @@ def mk_graph(repo, category=BugCategory.STABLEREQ):
151153 graph .starting_nodes = set ()
152154 graph .targets = ()
153155 graph .target_arches = {}
156+ graph .stablereq_check = SimpleNamespace (feed = lambda pkgs : iter (()))
157+ graph ._stablereq_due = {}
154158 return graph
155159
156160
@@ -648,3 +652,123 @@ def test_single_package_target_is_unchanged(self, repo):
648652 graph , _ = self .mk_stablereq_graph (repo , {"cat/a-2" })
649653 graph .load_targets ([(None , parserestrict .parse_match ("cat/a" ), frozenset ())])
650654 assert [str (pkg .versioned_atom ) for pkg in graph .targets ] == ["=cat/a-2" ]
655+
656+
657+ STABLE_THEN_UNSTABLE = {
658+ "1" : {"KEYWORDS" : ["amd64" ]},
659+ "2" : {"KEYWORDS" : ["~amd64" ]},
660+ "3" : {"KEYWORDS" : ["~amd64" ]},
661+ }
662+
663+
664+ class TestFindBestMatch :
665+ """Each step of the preference chain deciding which version gets filed."""
666+
667+ def mk (self , repo , versions = None , masks = (), due = ()):
668+ for ver , kwargs in (versions or STABLE_THEN_UNSTABLE ).items ():
669+ repo .create_ebuild (f"cat/dep-{ ver } " , ** kwargs )
670+ if masks :
671+ with open (pjoin (repo .location , "profiles" , "package.mask" ), "w" ) as f :
672+ f .write ("\n " .join (masks ) + "\n " )
673+ repo .sync ()
674+
675+ graph = mk_graph (repo )
676+ if due :
677+
678+ def feed (pkgs ):
679+ for pkg in pkgs :
680+ if pkg .versioned_atom .cpvstr in due :
681+ yield bugs .stablereq .StableRequest (
682+ slot = pkg .slot , keywords = pkg .keywords , age = 40 , pkg = pkg
683+ )
684+
685+ graph .stablereq_check = SimpleNamespace (feed = feed )
686+ graph .options .filter_stablereqs = True
687+ return graph , repo .match (atom ("cat/dep" ))
688+
689+ @staticmethod
690+ def pick (graph , pkgset , ** kwargs ):
691+ return str (graph .find_best_match ([atom ("cat/dep" )], pkgset , ** kwargs ).versioned_atom )
692+
693+ @staticmethod
694+ def version (pkgset , fullver ):
695+ return next (pkg for pkg in pkgset if pkg .fullver == fullver )
696+
697+ def test_a_user_selected_target_wins (self , repo ):
698+ graph , pkgset = self .mk (repo )
699+ graph .targets = (self .version (pkgset , "2" ),)
700+ assert self .pick (graph , pkgset ) == "=cat/dep-2"
701+
702+ def test_the_newest_user_selected_target_wins (self , repo ):
703+ graph , pkgset = self .mk (repo )
704+ graph .targets = (self .version (pkgset , "1" ), self .version (pkgset , "2" ))
705+ assert self .pick (graph , pkgset ) == "=cat/dep-2"
706+
707+ def test_a_package_already_in_the_graph_wins (self , repo ):
708+ graph , pkgset = self .mk (repo )
709+ graph .nodes = {bugs .GraphNode (((self .version (pkgset , "2" ), {"*" }),))}
710+ assert self .pick (graph , pkgset ) == "=cat/dep-2"
711+
712+ def test_a_user_target_beats_the_graph (self , repo ):
713+ graph , pkgset = self .mk (repo )
714+ graph .targets = (self .version (pkgset , "1" ),)
715+ graph .nodes = {bugs .GraphNode (((self .version (pkgset , "3" ), {"*" }),))}
716+ assert self .pick (graph , pkgset ) == "=cat/dep-1"
717+
718+ def test_the_stablereq_due_version_wins (self , repo ):
719+ graph , pkgset = self .mk (repo , due = {"cat/dep-2" })
720+ assert self .pick (graph , pkgset ) == "=cat/dep-2"
721+
722+ def test_the_graph_beats_the_stablereq_due_version (self , repo ):
723+ graph , pkgset = self .mk (repo , due = {"cat/dep-2" })
724+ graph .nodes = {bugs .GraphNode (((self .version (pkgset , "3" ), {"*" }),))}
725+ assert self .pick (graph , pkgset ) == "=cat/dep-3"
726+
727+ def test_the_stablereq_step_needs_filter_stablereqs (self , repo ):
728+ graph , pkgset = self .mk (repo , due = {"cat/dep-2" })
729+ graph .options .filter_stablereqs = False
730+ assert self .pick (graph , pkgset ) == "=cat/dep-1"
731+
732+ def test_a_due_version_outside_the_candidates_is_passed_over (self , repo ):
733+ graph , pkgset = self .mk (repo , due = {"cat/dep-3" })
734+ candidates = [pkg for pkg in pkgset if pkg .fullver != "3" ]
735+ assert self .pick (graph , candidates ) == "=cat/dep-1"
736+
737+ def test_the_stablereq_answer_is_cached_per_package (self , repo ):
738+ graph , pkgset = self .mk (repo , due = {"cat/dep-2" })
739+ calls = []
740+ inner = graph .stablereq_check .feed
741+ graph .stablereq_check = SimpleNamespace (feed = lambda pkgs : (calls .append (1 ), inner (pkgs ))[1 ])
742+ self .pick (graph , pkgset )
743+ self .pick (graph , pkgset )
744+ assert len (calls ) == 1
745+
746+ def test_a_semi_stable_version_beats_a_newer_unstable_one (self , repo ):
747+ graph , pkgset = self .mk (repo )
748+ assert self .pick (graph , pkgset ) == "=cat/dep-1"
749+
750+ def test_the_newest_wins_when_semi_stable_is_not_preferred (self , repo ):
751+ graph , pkgset = self .mk (repo )
752+ assert self .pick (graph , pkgset , prefer_semi_stable = False ) == "=cat/dep-3"
753+
754+ def test_versions_without_keywords_are_passed_over (self , repo ):
755+ versions = dict (STABLE_THEN_UNSTABLE , ** {"3" : {"KEYWORDS" : []}})
756+ graph , pkgset = self .mk (repo , versions )
757+ assert self .pick (graph , pkgset , prefer_semi_stable = False ) == "=cat/dep-2"
758+
759+ def test_the_newest_is_the_last_resort (self , repo ):
760+ versions = {ver : {"KEYWORDS" : []} for ver in ("1" , "2" , "3" )}
761+ graph , pkgset = self .mk (repo , versions )
762+ assert self .pick (graph , pkgset ) == "=cat/dep-3"
763+
764+ def test_live_versions_are_excluded (self , repo ):
765+ # keyworded, so only the live filter can keep it out of the running
766+ versions = dict (
767+ STABLE_THEN_UNSTABLE , ** {"9999" : {"PROPERTIES" : "live" , "KEYWORDS" : ["~amd64" ]}}
768+ )
769+ graph , pkgset = self .mk (repo , versions )
770+ assert self .pick (graph , pkgset , prefer_semi_stable = False ) == "=cat/dep-3"
771+
772+ def test_masked_versions_are_excluded (self , repo ):
773+ graph , pkgset = self .mk (repo , masks = ("=cat/dep-3" ,))
774+ assert self .pick (graph , pkgset , prefer_semi_stable = False ) == "=cat/dep-2"
0 commit comments