@@ -724,7 +724,64 @@ type ArrayModule() =
724724 let nullArr = null : string[]
725725 CheckThrowsArgumentNullException ( fun () -> Array.filter funcStr nullArr |> ignore)
726726
727- ()
727+ ()
728+
729+ [<Test>]
730+ member this.Filter2 () =
731+ // The Array.filter algorith uses a bitmask as a temporary storage mechanism
732+ // for which elements to filter. This introduces some possible error conditions
733+ // around how the filter is filled and subsequently used, so filter test
734+ // does a pretty exhaustive test suite.
735+ // It works by first generating arrays which consist of sequences of unique
736+ // positive and negative numbers, as per arguments, it then filters for the
737+ // positive values, and then compares the results agains the original array.
738+
739+ let makeTestArray size posLength negLength startWithPos startFromEnd =
740+ let array = Array.zeroCreate size
741+
742+ let mutable sign = if startWithPos then 1 else - 1
743+ let mutable count = if startWithPos then posLength else negLength
744+ for i = 1 to size do
745+ let idx = if startFromEnd then size- i else i-1
746+ array.[ idx] <- ( idx+ 1 ) * sign
747+ count <- count - 1
748+ if count <= 0 then
749+ sign <- sign * - 1
750+ count <- if sign > 0 then posLength else negLength
751+
752+ array
753+
754+ let checkFilter filter ( array : array < _ >) =
755+ let filtered = array |> filter ( fun n -> n > 0 )
756+
757+ let mutable idx = 0
758+ for item in filtered do
759+ while array.[ idx] < item do
760+ idx <- idx + 1
761+ if item <> array.[ idx] then
762+ Assert.Fail ()
763+ idx <- idx + 1
764+ while idx < array.Length do
765+ if array.[ idx] > 0 then
766+ Assert.Fail ()
767+ idx <- idx + 1
768+
769+ let checkCombinations filter maxSize =
770+ for size = 0 to maxSize do
771+ for posLength = 1 to size do
772+ for negLength = 1 to size do
773+ for startWithPos in [ true ; false ] do
774+ for startFromEnd in [ true ; false ] do
775+ let testArray = makeTestArray size posLength negLength startWithPos startFromEnd
776+ checkFilter filter testArray
777+
778+ // this could probably be a bit smaller, but needs to at least be > 64 to test chunk copying
779+ // of data, and > 96 gives a safer feel, so settle on a nice decimal rounding of one hundred
780+ // to appease those with digits.
781+ let suitableTestMaxLength = 100
782+
783+ checkCombinations Array.filter suitableTestMaxLength
784+
728785
729786
730787 [<Test>]
0 commit comments