1717import logging
1818
1919from django .contrib .auth .models import User
20+ from django .contrib .contenttypes .models import ContentType
2021from django .test import override_settings
2122from django .utils import timezone
2223
24+ from dojo .location .models import Location , LocationFindingReference , LocationProductReference
2325from dojo .models import Endpoint , Engagement , Finding , Product , Product_Type , Test , Test_Type
2426from dojo .product .helpers import propagate_tags_on_product_sync
2527from unittests .dojo_test_case import (
@@ -137,6 +139,16 @@ def setUpTestData(cls):
137139 ss .enable_product_tag_inheritance = True
138140 ss .save ()
139141
142+ # Warm up ContentType cache for models touched by the propagation
143+ # paths so first-call ContentType lookups don't count against the
144+ # measured sections (matches the pattern in test_importers_performance).
145+ # Without this, the first test in a fresh process to exercise the V3
146+ # Location path pays a one-time lookup, producing a matrix-dependent
147+ # off-by-one when CI runs with V3_FEATURE_LOCATIONS true vs false at
148+ # startup.
149+ for model in [Endpoint , Engagement , Finding , Location , LocationFindingReference , LocationProductReference , Product , Product_Type , Test , Test_Type ]:
150+ ContentType .objects .get_for_model (model )
151+
140152 # ------------------------------------------------------------------
141153 # Helpers shared by V2/V3 variants of the same scenario.
142154 # ------------------------------------------------------------------
@@ -317,7 +329,6 @@ def test_baseline_product_tag_add_propagates_to_100_locations_v3(self):
317329 product .tags .add ("perf-added-loc" )
318330 propagate_tags_on_product_sync (product )
319331
320- from dojo .location .models import Location # noqa: PLC0415
321332 loc = Location .objects .filter (products__product = product ).first ()
322333 self .assertIsNotNone (loc )
323334 self .assertIn ("perf-added-loc" , [t .name for t in loc .tags .all ()])
@@ -332,7 +343,6 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self):
332343 product .tags .remove ("to-remove-loc" )
333344 propagate_tags_on_product_sync (product )
334345
335- from dojo .location .models import Location # noqa: PLC0415
336346 loc = Location .objects .filter (products__product = product ).first ()
337347 self .assertIsNotNone (loc )
338348 location_tag_names = {t .name for t in loc .tags .all ()}
@@ -367,7 +377,7 @@ def test_baseline_product_tag_remove_propagates_to_100_locations_v3(self):
367377 EXPECTED_PRODUCT_TAG_REMOVE_100_ENDPOINTS = 3740
368378
369379 # V3 location paths (LocationManager has no V2 counterpart in this class).
370- EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4532
380+ EXPECTED_PRODUCT_TAG_ADD_100_LOCATIONS = 4531
371381 EXPECTED_PRODUCT_TAG_REMOVE_100_LOCATIONS = 4307
372382
373383
0 commit comments