@@ -64,6 +64,140 @@ public TopicMappingServiceTest(TopicInfrastructureFixture<StubTopicRepository> f
6464
6565 }
6666
67+ /*==========================================================================================================================
68+ | TEST: MAP: LOAD TESTING: EVALUATE THRESHOLD
69+ \-------------------------------------------------------------------------------------------------------------------------*/
70+ /// <summary>
71+ /// Establishes a <see cref="TopicMappingService"/> and tests creating and mapping <see cref="Topic"/> instances in bulk,
72+ /// as a quick-and-easy way of assessing performance.
73+ /// </summary>
74+ /// <remarks>
75+ /// <para>
76+ /// The <see cref="TopicMappingService"/> includes functionality to map properties to attributes via a constructor that
77+ /// accepts a <see cref="AttributeDictionary"/>. This introduces some overhead which is not cost effective if there are
78+ /// not any attributes that map to properties. For larger numbers of mapped attributes, however, the <see cref="
79+ /// AttributeDictionary"/> can reduce the mapping time considerably, while also giving more control over the model
80+ /// construction to the model developer. This test is intended to help identify and optimize that threshold based on
81+ /// improvements to the underlying <see cref="AttributeDictionary"/>, <see cref="TopicMappingService.MapAsync(Topic?,
82+ /// AssociationTypes)"/>, and <see cref="AttributeCollection.AsAttributeDictionary(bool)"/> convenience method.
83+ /// </para>
84+ /// <para>
85+ /// This is only intended to be enabled when needed for specialized performance testing.
86+ /// </para>
87+ /// </remarks>
88+ [ Fact ]
89+ public async Task Map_Bulk_EvaluateThreshold ( ) {
90+
91+ /*------------------------------------------------------------------------------------------------------------------------
92+ | Establish variables
93+ \-----------------------------------------------------------------------------------------------------------------------*/
94+ var runs = 0 ; // The number of mapping operations to perform
95+ var propertyCount = 10 ; // The number of property values to set on the LoadTestingModel
96+
97+ /*------------------------------------------------------------------------------------------------------------------------
98+ | Establish data model
99+ \-----------------------------------------------------------------------------------------------------------------------*/
100+ var topic = new Topic ( "Test" , "ContentList" , null ) ;
101+
102+ for ( var i = 0 ; i <= propertyCount ; i ++ ) {
103+ topic . Attributes . SetInteger ( "Property" + i , i ) ;
104+ }
105+
106+ /*------------------------------------------------------------------------------------------------------------------------
107+ | Run load testing
108+ \-----------------------------------------------------------------------------------------------------------------------*/
109+ for ( var i = 0 ; i < runs ; i ++ ) {
110+ await _mappingService . MapAsync < LoadTestingViewModel > ( topic ) . ConfigureAwait ( false ) ;
111+ }
112+
113+ /*------------------------------------------------------------------------------------------------------------------------
114+ | Always assume the test passed
115+ \-----------------------------------------------------------------------------------------------------------------------*/
116+ Assert . True ( true ) ;
117+
118+ }
119+
120+ /*==========================================================================================================================
121+ | TEST: MAP: LOAD TESTING: EVALUATE TIME
122+ \-------------------------------------------------------------------------------------------------------------------------*/
123+ /// <summary>
124+ /// Establishes a <see cref="TopicMappingService"/> and tests creating and mapping <see cref="Topic"/> instances in bulk,
125+ /// as a quick-and-easy way of assessing performance.
126+ /// </summary>
127+ [ Fact ]
128+ public async Task Map_LoadTesting_EvaluateTime ( ) {
129+
130+ /*------------------------------------------------------------------------------------------------------------------------
131+ | Establish variables
132+ \-----------------------------------------------------------------------------------------------------------------------*/
133+ var runs = 0 ; // The number of mapping operations to perform
134+ var useFullAttributeSet = false ; // Include a larget set of attribute values
135+ var includeNestedTopics = false ; // Only include a minimal set of properties
136+
137+ /*------------------------------------------------------------------------------------------------------------------------
138+ | Establish object model
139+ \-----------------------------------------------------------------------------------------------------------------------*/
140+ var currentId = 1 ;
141+ var baseTopic = new Topic ( "Base" , "Page" , null , currentId ++ ) ;
142+ var grandparent = new Topic ( "Grandparent" , "Page" , null , currentId ++ ) ;
143+ var parent = new Topic ( "Parent" , "Page" , grandparent , currentId ++ ) ;
144+ var topic = new Topic ( "Test" , "ContentList" , parent , currentId ++ ) ;
145+ var contentItems = new Topic ( "ContentItems" , "List" , topic , currentId ++ ) ;
146+
147+ if ( includeNestedTopics ) {
148+ _ = new Topic ( "Item1" , "ContentItem" , contentItems , currentId ++ ) ;
149+ _ = new Topic ( "Item2" , "ContentItem" , contentItems , currentId ++ ) ;
150+ _ = new Topic ( "Item3" , "ContentItem" , contentItems , currentId ++ ) ;
151+ _ = new Topic ( "Item4" , "ContentItem" , contentItems , currentId ++ ) ;
152+ _ = new Topic ( "Item5" , "ContentItem" , contentItems , currentId ++ ) ;
153+ _ = new Topic ( "Item6" , "ContentItem" , contentItems , currentId ++ ) ;
154+ }
155+
156+ grandparent . BaseTopic = baseTopic ;
157+
158+ /*------------------------------------------------------------------------------------------------------------------------
159+ | Populate attributes
160+ \-----------------------------------------------------------------------------------------------------------------------*/
161+ foreach ( var contentItem in contentItems . Children ) {
162+ contentItem . Attributes . SetDateTime ( "LastModified" , DateTime . Now ) ;
163+ contentItem . Attributes . SetValue ( "Description" , "Value1" ) ;
164+ if ( useFullAttributeSet ) {
165+ contentItem . Attributes . SetValue ( "LearnMoreUrl" , "/Topic/23/" ) ;
166+ contentItem . Attributes . SetValue ( "ThumbnailImage" , "/Image.jpg" ) ;
167+ contentItem . Attributes . SetValue ( "Description" , "Value1" ) ;
168+ contentItem . Attributes . SetValue ( "Category" , "Gumby" ) ;
169+ }
170+ }
171+
172+ topic . Attributes . SetValue ( "Title" , "Friendly Title" ) ;
173+ topic . Attributes . SetValue ( "IsHidden" , "0" ) ;
174+ if ( useFullAttributeSet ) {
175+ topic . Attributes . SetValue ( "View" , "Test" ) ;
176+ topic . Attributes . SetValue ( "ShortTitle" , "Short Title" ) ;
177+ topic . Attributes . SetValue ( "Subtitle" , "Subtitle" ) ;
178+ topic . Attributes . SetValue ( "MetaTitle" , "Meta Title" ) ;
179+ topic . Attributes . SetValue ( "MetaDescription" , "Meta Description" ) ;
180+ topic . Attributes . SetValue ( "MetaKeywords" , "Load;Test;Keywords" ) ;
181+ topic . Attributes . SetValue ( "NoIndex" , "0" ) ;
182+ topic . Attributes . SetValue ( "Body" , "Body of test topic" ) ;
183+ }
184+
185+ baseTopic . Attributes . SetValue ( "Title" , "Inherited Title" ) ;
186+
187+ /*------------------------------------------------------------------------------------------------------------------------
188+ | Run load testing
189+ \-----------------------------------------------------------------------------------------------------------------------*/
190+ for ( var i = 0 ; i <= runs ; i ++ ) {
191+ await _mappingService . MapAsync ( topic ) . ConfigureAwait ( false ) ;
192+ }
193+
194+ /*------------------------------------------------------------------------------------------------------------------------
195+ | Always assume the test passed
196+ \-----------------------------------------------------------------------------------------------------------------------*/
197+ Assert . True ( true ) ;
198+
199+ }
200+
67201 /*==========================================================================================================================
68202 | TEST: MAP: GENERIC: RETURNS NEW MODEL
69203 \-------------------------------------------------------------------------------------------------------------------------*/
@@ -1444,6 +1578,7 @@ public async Task Map_FlattenAttribute_ExcludeTopics() {
14441578 Assert . Single ( target ? . Children ) ;
14451579
14461580 }
1581+
14471582 /*==========================================================================================================================
14481583 | TEST: MAP: CACHED TOPIC: RETURNS CACHED MODEL
14491584 \-------------------------------------------------------------------------------------------------------------------------*/
0 commit comments