Add subsetOf Filter function
parent
3739043f87
commit
e8ee125def
|
@ -3,6 +3,7 @@ module Internal.Filter.Timeline exposing
|
|||
, pass, onlySenders, allSendersExcept, onlyTypes, allTypesExcept, fail
|
||||
, match, run
|
||||
, and
|
||||
, subsetOf
|
||||
)
|
||||
|
||||
{-|
|
||||
|
@ -33,6 +34,11 @@ for interacting with the Matrix API.
|
|||
|
||||
@docs and
|
||||
|
||||
|
||||
## Compare
|
||||
|
||||
@docs subsetOf
|
||||
|
||||
-}
|
||||
|
||||
import Set exposing (Set)
|
||||
|
@ -132,15 +138,15 @@ and (Filter f1) (Filter f2) =
|
|||
|
||||
( False, False ) ->
|
||||
Set.intersect f1.types f2.types
|
||||
, typesAllowOthers = f2.typesAllowOthers && f2.typesAllowOthers
|
||||
, typesAllowOthers = f1.typesAllowOthers && f2.typesAllowOthers
|
||||
}
|
||||
in
|
||||
case stdAnd of
|
||||
Filter f ->
|
||||
if Set.isEmpty f.senders && (not f.sendersAllowOthers) then
|
||||
if Set.isEmpty f.senders && not f.sendersAllowOthers then
|
||||
fail
|
||||
|
||||
else if Set.isEmpty f.types && (not f.typesAllowOthers) then
|
||||
else if Set.isEmpty f.types && not f.typesAllowOthers then
|
||||
fail
|
||||
|
||||
else
|
||||
|
@ -235,3 +241,36 @@ pass =
|
|||
run : Filter -> List (Event a) -> List (Event a)
|
||||
run f events =
|
||||
List.filter (match f) events
|
||||
|
||||
|
||||
{-| Determine whether the second argument is a subset filter of the first
|
||||
argument.
|
||||
-}
|
||||
subsetOf : Filter -> Filter -> Bool
|
||||
subsetOf (Filter big) (Filter small) =
|
||||
let
|
||||
isSSof : Set String -> Set String -> Bool
|
||||
isSSof b s =
|
||||
Set.intersect b s == s
|
||||
|
||||
isSubsetFor : ( Bool, Set String ) -> ( Bool, Set String ) -> Bool
|
||||
isSubsetFor ( bb, sb ) ( bs, ss ) =
|
||||
case ( bb, bs ) of
|
||||
( True, True ) ->
|
||||
isSSof ss sb
|
||||
|
||||
( True, False ) ->
|
||||
Set.isEmpty (Set.intersect sb ss)
|
||||
|
||||
( False, True ) ->
|
||||
False
|
||||
|
||||
( False, False ) ->
|
||||
isSSof sb ss
|
||||
in
|
||||
isSubsetFor
|
||||
( big.sendersAllowOthers, big.senders )
|
||||
( small.sendersAllowOthers, small.senders )
|
||||
&& isSubsetFor
|
||||
( big.typesAllowOthers, big.types )
|
||||
( small.typesAllowOthers, small.types )
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module Internal.Values.Event exposing
|
||||
( Event
|
||||
, UnsignedData(..), age, prevContent, redactedBecause, transactionId
|
||||
, encode, decoder, isEqual
|
||||
, encode, decoder
|
||||
, isEqual
|
||||
)
|
||||
|
||||
{-|
|
||||
|
@ -24,6 +25,7 @@ of a room.
|
|||
|
||||
@docs encode, decoder
|
||||
|
||||
|
||||
## Test functions
|
||||
|
||||
@docs isEqual
|
||||
|
@ -133,18 +135,24 @@ isEqual : Event -> Event -> Bool
|
|||
isEqual e1 e2 =
|
||||
if e1.eventId /= e2.eventId then
|
||||
False
|
||||
|
||||
else if e1.originServerTs /= e2.originServerTs then
|
||||
False
|
||||
|
||||
else if e1.roomId /= e2.roomId then
|
||||
False
|
||||
|
||||
else if e1.sender /= e2.sender then
|
||||
False
|
||||
|
||||
else if e1.stateKey /= e2.stateKey then
|
||||
False
|
||||
|
||||
else if e1.eventType /= e2.eventType then
|
||||
False
|
||||
|
||||
else
|
||||
case (e1.unsigned, e2.unsigned) of
|
||||
case ( e1.unsigned, e2.unsigned ) of
|
||||
( Nothing, Nothing ) ->
|
||||
True
|
||||
|
||||
|
@ -154,16 +162,19 @@ isEqual e1 e2 =
|
|||
( Nothing, Just _ ) ->
|
||||
False
|
||||
|
||||
( Just ( UnsignedData d1), Just ( UnsignedData d2 )) ->
|
||||
( Just (UnsignedData d1), Just (UnsignedData d2) ) ->
|
||||
if d1.age /= d2.age then
|
||||
False
|
||||
|
||||
else if d1.transactionId /= d2.transactionId then
|
||||
False
|
||||
|
||||
else if Maybe.map (E.encode 0) d1.prevContent /= Maybe.map (E.encode 0) d2.prevContent then
|
||||
False
|
||||
|
||||
else
|
||||
case (d1.redactedBecause, d2.redactedBecause) of
|
||||
( Nothing, Nothing) ->
|
||||
case ( d1.redactedBecause, d2.redactedBecause ) of
|
||||
( Nothing, Nothing ) ->
|
||||
True
|
||||
|
||||
( Nothing, Just _ ) ->
|
||||
|
@ -175,6 +186,7 @@ isEqual e1 e2 =
|
|||
( Just se1, Just se2 ) ->
|
||||
isEqual se1 se2
|
||||
|
||||
|
||||
{-| Determine the previous `content` value for this event. This field is only a
|
||||
`Just value` if the event is a state event, and the Matrix Vault has permission
|
||||
to see the previous content.
|
||||
|
|
|
@ -4,6 +4,7 @@ import Expect
|
|||
import Fuzz exposing (Fuzzer)
|
||||
import Internal.Filter.Timeline as Filter exposing (Filter)
|
||||
import Internal.Values.Event as Event
|
||||
import Set
|
||||
import Test exposing (..)
|
||||
import Test.Values.Event as TestEvent
|
||||
|
||||
|
@ -138,6 +139,138 @@ suite =
|
|||
|> Filter.and (Filter.allTypesExcept types)
|
||||
|> Expect.equal Filter.fail
|
||||
)
|
||||
, fuzz2 (Fuzz.list Fuzz.string)
|
||||
(Fuzz.list Fuzz.string)
|
||||
"Only list + all except list = common types"
|
||||
(\t1 t2 ->
|
||||
Expect.equal
|
||||
(Filter.and
|
||||
(Filter.onlyTypes t1)
|
||||
(Filter.allTypesExcept t2)
|
||||
)
|
||||
(Set.diff (Set.fromList t1) (Set.fromList t2)
|
||||
|> Set.toList
|
||||
|> Filter.onlyTypes
|
||||
)
|
||||
)
|
||||
, fuzz2 (Fuzz.list Fuzz.string)
|
||||
(Fuzz.list Fuzz.string)
|
||||
"Only list + all except list = common senders"
|
||||
(\t1 t2 ->
|
||||
Expect.equal
|
||||
(Filter.and
|
||||
(Filter.onlySenders t1)
|
||||
(Filter.allSendersExcept t2)
|
||||
)
|
||||
(Set.diff (Set.fromList t1) (Set.fromList t2)
|
||||
|> Set.toList
|
||||
|> Filter.onlySenders
|
||||
)
|
||||
)
|
||||
]
|
||||
, describe "Subset testing"
|
||||
[ fuzz2 fuzzer
|
||||
fuzzer
|
||||
"Combining two filters is always a subset"
|
||||
(\filter1 filter2 ->
|
||||
filter1
|
||||
|> Filter.and filter2
|
||||
|> Expect.all
|
||||
[ Filter.subsetOf filter1 >> Expect.equal True
|
||||
, Filter.subsetOf filter2 >> Expect.equal True
|
||||
]
|
||||
)
|
||||
, fuzz
|
||||
(Fuzz.bool
|
||||
|> Fuzz.andThen
|
||||
(\same ->
|
||||
if same then
|
||||
Fuzz.map (\a -> ( a, a )) fuzzer
|
||||
|
||||
else
|
||||
Fuzz.map2 Tuple.pair fuzzer fuzzer
|
||||
)
|
||||
)
|
||||
"subset goes both way iff equal"
|
||||
(\( filter1, filter2 ) ->
|
||||
Expect.equal
|
||||
(filter1 == filter2)
|
||||
(Filter.subsetOf filter1 filter2
|
||||
&& Filter.subsetOf filter2 filter1
|
||||
)
|
||||
)
|
||||
, fuzz2 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
"One more excluded sender is a subset"
|
||||
(\head tail ->
|
||||
Filter.allSendersExcept (head :: tail)
|
||||
|> Filter.subsetOf (Filter.allSendersExcept tail)
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz2 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
"One more excluded type is a subset"
|
||||
(\head tail ->
|
||||
Filter.allTypesExcept (head :: tail)
|
||||
|> Filter.subsetOf (Filter.allTypesExcept tail)
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz2 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
"One less included sender is a subset"
|
||||
(\head tail ->
|
||||
Filter.onlySenders tail
|
||||
|> Filter.subsetOf (Filter.onlySenders (head :: tail))
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz2 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
"One less included type is a subset"
|
||||
(\head tail ->
|
||||
Filter.onlyTypes tail
|
||||
|> Filter.subsetOf (Filter.onlyTypes (head :: tail))
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz3 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
fuzzer
|
||||
"One more excluded sender is a subset - even when combined with another fuzzer"
|
||||
(\head tail filter ->
|
||||
Filter.allSendersExcept (head :: tail)
|
||||
|> Filter.and filter
|
||||
|> Filter.subsetOf (Filter.and filter <| Filter.allSendersExcept tail)
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz3 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
fuzzer
|
||||
"One more excluded type is a subset - even when combined with another fuzzer"
|
||||
(\head tail filter ->
|
||||
Filter.allTypesExcept (head :: tail)
|
||||
|> Filter.and filter
|
||||
|> Filter.subsetOf (Filter.and filter <| Filter.allTypesExcept tail)
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz3 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
fuzzer
|
||||
"One less included sender is a subset - even when combined with another fuzzer"
|
||||
(\head tail filter ->
|
||||
Filter.onlySenders tail
|
||||
|> Filter.and filter
|
||||
|> Filter.subsetOf (Filter.and filter <| Filter.onlySenders (head :: tail))
|
||||
|> Expect.equal True
|
||||
)
|
||||
, fuzz3 Fuzz.string
|
||||
(Fuzz.list Fuzz.string)
|
||||
fuzzer
|
||||
"One less included type is a subset - even when combined with another fuzzer"
|
||||
(\head tail filter ->
|
||||
Filter.onlyTypes tail
|
||||
|> Filter.and filter
|
||||
|> Filter.subsetOf (Filter.and filter <| Filter.onlyTypes (head :: tail))
|
||||
|> Expect.equal True
|
||||
)
|
||||
]
|
||||
, describe "Use case testing"
|
||||
[ fuzz3 (Fuzz.list TestEvent.fuzzer)
|
||||
|
@ -150,30 +283,29 @@ suite =
|
|||
l1 =
|
||||
events
|
||||
|> Filter.run
|
||||
( Filter.and
|
||||
( Filter.onlySenders senders )
|
||||
( Filter.onlyTypes types )
|
||||
(Filter.and
|
||||
(Filter.onlySenders senders)
|
||||
(Filter.onlyTypes types)
|
||||
)
|
||||
|
||||
l2 : List Event.Event
|
||||
l2 =
|
||||
( List.filter
|
||||
List.filter
|
||||
(\e ->
|
||||
(List.member e.sender senders) &&
|
||||
(List.member e.eventType types)
|
||||
List.member e.sender senders
|
||||
&& List.member e.eventType types
|
||||
)
|
||||
events
|
||||
)
|
||||
in
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
)
|
||||
, fuzz3 (Fuzz.list TestEvent.fuzzer)
|
||||
(Fuzz.list Fuzz.string)
|
||||
|
@ -185,30 +317,29 @@ suite =
|
|||
l1 =
|
||||
events
|
||||
|> Filter.run
|
||||
( Filter.and
|
||||
( Filter.onlySenders senders )
|
||||
( Filter.allTypesExcept types )
|
||||
(Filter.and
|
||||
(Filter.onlySenders senders)
|
||||
(Filter.allTypesExcept types)
|
||||
)
|
||||
|
||||
l2 : List Event.Event
|
||||
l2 =
|
||||
( List.filter
|
||||
List.filter
|
||||
(\e ->
|
||||
(List.member e.sender senders) &&
|
||||
(not <| List.member e.eventType types)
|
||||
List.member e.sender senders
|
||||
&& (not <| List.member e.eventType types)
|
||||
)
|
||||
events
|
||||
)
|
||||
in
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
)
|
||||
, fuzz3 (Fuzz.list TestEvent.fuzzer)
|
||||
(Fuzz.list Fuzz.string)
|
||||
|
@ -220,30 +351,29 @@ suite =
|
|||
l1 =
|
||||
events
|
||||
|> Filter.run
|
||||
( Filter.and
|
||||
( Filter.allSendersExcept senders )
|
||||
( Filter.onlyTypes types )
|
||||
(Filter.and
|
||||
(Filter.allSendersExcept senders)
|
||||
(Filter.onlyTypes types)
|
||||
)
|
||||
|
||||
l2 : List Event.Event
|
||||
l2 =
|
||||
( List.filter
|
||||
List.filter
|
||||
(\e ->
|
||||
(not <| List.member e.sender senders) &&
|
||||
(List.member e.eventType types)
|
||||
(not <| List.member e.sender senders)
|
||||
&& List.member e.eventType types
|
||||
)
|
||||
events
|
||||
)
|
||||
in
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
)
|
||||
, fuzz3 (Fuzz.list TestEvent.fuzzer)
|
||||
(Fuzz.list Fuzz.string)
|
||||
|
@ -255,30 +385,29 @@ suite =
|
|||
l1 =
|
||||
events
|
||||
|> Filter.run
|
||||
( Filter.and
|
||||
( Filter.allSendersExcept senders )
|
||||
( Filter.allTypesExcept types )
|
||||
(Filter.and
|
||||
(Filter.allSendersExcept senders)
|
||||
(Filter.allTypesExcept types)
|
||||
)
|
||||
|
||||
l2 : List Event.Event
|
||||
l2 =
|
||||
( List.filter
|
||||
List.filter
|
||||
(\e ->
|
||||
(not <| List.member e.sender senders) &&
|
||||
(not <| List.member e.eventType types)
|
||||
(not <| List.member e.sender senders)
|
||||
&& (not <| List.member e.eventType types)
|
||||
)
|
||||
events
|
||||
)
|
||||
in
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
Expect.all
|
||||
[ Expect.equal (List.length l1) (List.length l2)
|
||||
|> always
|
||||
, List.map2 Event.isEqual l1 l2
|
||||
|> List.all identity
|
||||
|> Expect.equal True
|
||||
|> always
|
||||
]
|
||||
()
|
||||
)
|
||||
]
|
||||
]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
module Test.Values.Event exposing (..)
|
||||
|
||||
import Expect
|
||||
import Fuzz exposing (Fuzzer)
|
||||
import Internal.Values.Event as Event exposing (Event)
|
||||
import Json.Encode as E
|
||||
import Test exposing (..)
|
||||
import Test.Tools.Timestamp as TestTimestamp
|
||||
import Expect
|
||||
|
||||
|
||||
fuzzer : Fuzzer Event
|
||||
|
@ -67,10 +67,12 @@ valueFuzzer =
|
|||
, Fuzz.map Event.encode (Fuzz.lazy (\_ -> fuzzer))
|
||||
]
|
||||
|
||||
|
||||
suite : Test
|
||||
suite =
|
||||
describe "Sanity check"
|
||||
[ fuzz fuzzer "event = event"
|
||||
[ fuzz fuzzer
|
||||
"event = event"
|
||||
(\event ->
|
||||
Event.isEqual event event
|
||||
|> Expect.equal True
|
||||
|
|
Loading…
Reference in New Issue