@@ -17,6 +17,17 @@ type FlatListTests () =
1717 /// The array under a flat list, to tell whether two flat lists share their storage.
1818 static let underlying ( array : FlatList < int >) = ImmutableCollectionsMarshal.AsArray array
1919
20+ /// Asserts that an action rejects a default flat list with an ArgumentNullException that names the parameter.
21+ static let assertRejectsDefault ( name : string ) ( paramName : string ) ( actual : unit -> unit ) =
22+ let ex =
23+ Assert.ThrowsExactly< ArgumentNullException>( Action actual, $" FlatList.%s {name} must reject a default flat list" )
24+
25+ Assert.AreEqual< string | null >(
26+ paramName,
27+ ex.ParamName,
28+ $" FlatList.%s {name} must name the parameter of the default flat list"
29+ )
30+
2031 /// The functions that mirror an Array function, by name, with that function on a null array and the function on a
2132 /// default flat list. The rows of the test are the names: a function has no readable name in a row.
2233 static let arrayRejections =
@@ -209,6 +220,52 @@ type FlatListTests () =
209220 |> Array.map ( fun struct ( name , paramName , actual ) -> name, struct ( paramName, actual))
210221 |> Map.ofArray
211222
223+ /// The functions that take a sequence, by name, with the parameter that names a default flat list given as the
224+ /// sequence and the function on such a flat list. A default flat list converts to a sequence without a check and
225+ /// fails when the sequence is enumerated, so the other inputs are valid and the function would enumerate it.
226+ static let sequenceRejections =
227+ let defaultOuter = Unchecked.defaultof< FlatList< FlatList< int>>>
228+
229+ [|
230+ struct ( nameof FlatList.concat, " arrays" , ( fun () -> FlatList.concat ( defaultOuter :> seq<_>) |> ignore))
231+ struct ( nameof FlatList.transpose, " arrays" , ( fun () -> FlatList.transpose ( defaultOuter :> seq<_>) |> ignore))
232+ struct ( nameof FlatList.insertManyAt,
233+ " values" ,
234+ ( fun () ->
235+ FlatList.insertManyAt 1 ( defaultArray :> seq<_>) ( FlatList.ofArray Inputs.Several)
236+ |> ignore
237+ ))
238+ // Array.insertManyAt checks the source before the values
239+ struct ( $" %s {nameof FlatList.insertManyAt} (default source)" ,
240+ " source" ,
241+ ( fun () ->
242+ FlatList.insertManyAt 1 ( defaultArray :> seq<_>) defaultArray
243+ |> ignore
244+ ))
245+ struct ( nameof FlatList.except,
246+ " itemsToExclude" ,
247+ ( fun () ->
248+ FlatList.except ( defaultArray :> seq<_>) ( FlatList.ofArray Inputs.Several)
249+ |> ignore
250+ ))
251+ // Array.except returns an empty input without enumerating the items, but it checks the items for null first
252+ struct ( $" %s {nameof FlatList.except} (empty array)" ,
253+ " itemsToExclude" ,
254+ ( fun () ->
255+ FlatList.except ( defaultArray :> seq<_>) FlatList.empty< int>
256+ |> ignore
257+ ))
258+ // Array.except checks the items to exclude before the array
259+ struct ( $" %s {nameof FlatList.except} (default array)" ,
260+ " itemsToExclude" ,
261+ ( fun () ->
262+ FlatList.except ( defaultArray :> seq<_>) defaultArray
263+ |> ignore
264+ ))
265+ |]
266+ |> Array.map ( fun struct ( name , paramName , actual ) -> name, struct ( paramName, actual))
267+ |> Map.ofArray
268+
212269 /// The functions that take a range, by name, on the whole range of the input with several elements.
213270 static let wholeRanges : Map < string , FlatList < int > -> FlatList < int >> =
214271 Map.ofArray [|
@@ -245,6 +302,9 @@ type FlatListTests () =
245302 /// The names of the functions without an Array counterpart, as the rows of their test.
246303 static member OtherRejections = otherRejections.Keys
247304
305+ /// The names of the functions that take a sequence, as the rows of the test of a default flat list given as the sequence.
306+ static member SequenceRejections = sequenceRejections.Keys
307+
248308 /// The names of the functions that take a range, as the rows of the test of the whole range.
249309 static member WholeRanges = wholeRanges.Keys
250310
@@ -287,14 +347,28 @@ type FlatListTests () =
287347 [<TestMethod; DynamicData( nameof FlatListTests.OtherRejections) >]
288348 member _. ``functions without an Array counterpart reject a default flat list`` ( name : string ) =
289349 let struct ( paramName , actual ) = otherRejections[ name]
350+ assertRejectsDefault name paramName actual
290351
291- let ex =
292- Assert.ThrowsExactly< ArgumentNullException>( Action actual, $" FlatList.%s {name} must reject a default flat list" )
352+ [<TestMethod; DynamicData( nameof FlatListTests.SequenceRejections) >]
353+ member _. ``functions that take a sequence reject a default flat list given as the sequence`` ( name : string ) =
354+ let struct ( paramName , actual ) = sequenceRejections[ name]
355+ assertRejectsDefault name paramName actual
293356
294- Assert.AreEqual< string | null >(
295- paramName,
296- ex.ParamName,
297- $" FlatList.%s {name} must name the parameter of the default flat list"
357+ [<TestMethod; DataRow - 1 ; DataRow 9 >]
358+ member _. ``insertManyAt rejects an index out of range before default values as Array.insertManyAt does`` ( index : int ) =
359+ // The input has 8 elements, so the indices -1 and 9 are out of range. Array.insertManyAt checks the index
360+ // before it enumerates the values
361+ ExceptionAssert.Same (
362+ id,
363+ ( fun () ->
364+ Array.insertManyAt index Unchecked.defaultof< seq< int>> Inputs.Several
365+ |> ignore
366+ ),
367+ ( fun () ->
368+ FlatList.insertManyAt index ( defaultArray :> seq<_>) ( FlatList.ofArray Inputs.Several)
369+ |> ignore
370+ ),
371+ " FlatList.insertManyAt must check the index before the values as Array.insertManyAt does"
298372 )
299373
300374 [<TestMethod>]
0 commit comments