git.iko.soy/typeable/compaREST
on master help sign in
Fix some TODOs in schema and expand some comments (#72)

* Fix some TODOs in schema and expand some comments * Update src/OpenAPI/Checker/Validate/Schema.hs Co-authored-by: iko <ilyakooo0@gmail.com> Co-authored-by: iko <ilyakooo0@gmail.com>

commit6e454bcf2a96ce5d18fb676bc118f05165618b0c authormniip <mniip@users.noreply.github.com> dateFri 28 May 2021, 15:43 (5 years ago) parent1e7e283
2 files changed+52−32
openapi-diff.cabal+1 src/OpenAPI/Checker/Validate/Schema.hs+51−32
openapi-diff.cabal+1
@@ -53,6 +53,7 @@ common common-options
5353 , mtl
5454 , openapi3
5555 , optparse-applicative
56+ , pcre2
5657 , scientific
5758 , tagged
5859 , text
src/OpenAPI/Checker/Validate/Schema.hs+51−32
@@ -40,6 +40,7 @@ import qualified Data.Set as S
4040import Data.Text (Text)
4141import qualified Data.Text as T hiding (singleton)
4242import Data.Typeable
43+import Text.Regex.Pcre2
4344import OpenAPI.Checker.Behavior
4445import OpenAPI.Checker.Orphans ()
4546import OpenAPI.Checker.Paths
@@ -131,16 +132,16 @@ satisfiesTyped (TNumber n) (Maximum (Exclusive m)) = n < m
131132satisfiesTyped (TNumber n) (Maximum (Inclusive m)) = n <= m
132133satisfiesTyped (TNumber n) (Minimum (Down (Exclusive (Down m)))) = n > m
133134satisfiesTyped (TNumber n) (Minimum (Down (Inclusive (Down m)))) = n >= m
134−satisfiesTyped (TNumber n) (MultipleOf m) = denominator (toRational n / toRational m) == 1 -- TODO: could be better
135+satisfiesTyped (TNumber n) (MultipleOf m) = denominator (toRational n / toRational m) == 1 -- TODO: could be better #36
135136satisfiesTyped (TNumber n) (NumberFormat f) = checkNumberFormat f n
136137satisfiesTyped (TString s) (MaxLength m) = fromIntegral (T.length s) <= m
137138satisfiesTyped (TString s) (MinLength m) = fromIntegral (T.length s) >= m
138−satisfiesTyped (TString s) (Pattern p) = undefined s p -- TODO: regex stuff
139−satisfiesTyped (TString s) (StringFormat f) = undefined s f -- TODO: string format
139+satisfiesTyped (TString s) (Pattern p) = isJust $ match p s -- TODO: regex stuff #32
140+satisfiesTyped (TString s) (StringFormat f) = checkStringFormat f s
140141satisfiesTyped (TArray a) (Items f _) = all (`satisfies` f) a
141142satisfiesTyped (TArray a) (MaxItems m) = fromIntegral (F.length a) <= m
142143satisfiesTyped (TArray a) (MinItems m) = fromIntegral (F.length a) >= m
143−satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better
144+satisfiesTyped (TArray a) UniqueItems = S.size (S.fromList $ F.toList a) == F.length a -- TODO: could be better #36
144145satisfiesTyped (TObject o) (Properties props additional _) =
145146 all (`HM.member` o) (M.keys (M.filter propRequired props))
146147 && all (\(k, v) -> satisfies v $ maybe additional propFormula $ M.lookup k props) (HM.toList o)
@@ -160,6 +161,15 @@ checkNumberFormat "float" _n = True
160161checkNumberFormat "double" _n = True
161162checkNumberFormat f _n = error $ "Invalid number format: " <> T.unpack f
162163
164+checkStringFormat :: Format -> Text -> Bool
165+checkStringFormat "byte" _s = True -- TODO: regex stuff #32
166+checkStringFormat "binary" _s = True
167+checkStringFormat "date" _s = True
168+checkStringFormat "date-time" _s = True
169+checkStringFormat "password" _s = True
170+checkStringFormat "uuid" _s = True
171+checkStringFormat f _s = error $ "Invalid string format: " <> T.unpack f
172+
163173deriving stock instance Eq (Condition t)
164174
165175deriving stock instance Ord (Condition t)
@@ -351,29 +361,6 @@ instance
351361 , forObject = top
352362 }
353363
354−{- TODO: remove
355−instance Typeable t => Steppable Schema (Condition t) where
356− data Step Schema (Condition t)
357− = EnumField
358− | MaximumFields -- maximum & exclusiveMaximum
359− | MinimumFields -- minimum & exclusiveMinimum
360− | MultipleOfField
361− | FormatField
362− | MaxLengthField
363− | MinLengthField
364− | PatternField
365− | ItemsField
366− | MaxItemsField
367− | MinItemsField
368− | UniqueItemsField
369− | PropertiesFields -- properties, additionalProperties & required
370− | MaxPropertiesField
371− | MinPropertiesField
372− | NullableField
373− | IntegerType -- type=integer
374− deriving (Eq, Ord, Show)
375−-}
376−
377364instance Behavable 'SchemaLevel 'SchemaLevel where
378365 data Behave 'SchemaLevel 'SchemaLevel
379366 deriving (Eq, Ord, Show)
@@ -724,10 +711,10 @@ processSchema sch@(extract -> Schema {..}) = do
724711 , minPropertiesClause
725712 ])
726713
727−{- TODO: ReadOnly/WriteOnly -}
714+{- TODO: ReadOnly/WriteOnly #68 -}
728715
729716checkOneOfDisjoint :: [Traced (Referenced Schema)] -> ProcessM Bool
730−checkOneOfDisjoint = const $ pure True -- TODO
717+checkOneOfDisjoint = const $ pure True -- TODO #69
731718
732719schemaToFormula
733720 :: Traced (Definitions Schema)
@@ -788,7 +775,7 @@ checkContradiction
788775 :: Behavior 'TypedSchemaLevel
789776 -> [Condition t]
790777 -> SemanticCompatFormula ()
791−checkContradiction beh _ = issueAt beh NoContradiction -- TODO
778+checkContradiction beh _ = issueAt beh NoContradiction -- TODO #70
792779
793780checkImplication
794781 :: (HasAll (CheckEnv Schema) xs)
@@ -844,7 +831,7 @@ checkImplication env beh prods cons = case findExactly prods of
844831 Pattern p ->
845832 if any (\case Pattern p' -> p == p'; _ -> False) prods
846833 then pure ()
847− else issueAt beh (NoMatchingPattern p) -- TODO: regex comparison
834+ else issueAt beh (NoMatchingPattern p) -- TODO: regex comparison #32
848835 StringFormat f ->
849836 if any (\case StringFormat f' -> f == f'; _ -> False) prods
850837 then pure ()
@@ -872,7 +859,7 @@ checkImplication env beh prods cons = case findExactly prods of
872859 then pure ()
873860 else issueAt beh NoMatchingUniqueItems
874861 Properties props _ madd -> case findRelevant (<>) (\case Properties props' _ madd' -> Just $ (props', madd') NE.:| []; _ -> Nothing) prods of
875− Just ((props', madd') NE.:| []) -> do
862+ Just pm -> anyOfAt beh NoMatchingProperties $ NE.toList pm <&> \(props', madd') -> do
876863 F.for_ (S.fromList $ M.keys props <> M.keys props') $ \k -> do
877864 let go sch sch' = checkCompatibility env (beh >>> step (InProperty k)) (ProdCons sch sch')
878865 case (M.lookup k props', madd', M.lookup k props, madd) of
@@ -916,42 +903,74 @@ checkImplication env beh prods cons = case findExactly prods of
916903instance Issuable 'TypedSchemaLevel where
917904 data Issue 'TypedSchemaLevel
918905 = EnumDoesntSatisfy A.Value
906+ -- ^ producer produces a specific value ($1), consumer has a condition that is not satisfied by said value
919907 | NoMatchingEnum A.Value
908+ -- ^ producer produces a specific value ($1) which is not listed in the consumer's list of specific values
920909 | NoMatchingMaximum (Bound Scientific)
910+ -- ^ producer declares a maximum numeric value ($1), consumer doesnt
921911 | MatchingMaximumWeak (Bound Scientific) (Bound Scientific)
912+ -- ^ producer declares a maximum numeric value ($1), consumer declares a weaker (higher) limit ($2)
922913 | NoMatchingMinimum (Bound Scientific)
914+ -- ^ producer declares a minimum numeric value, consumer doesnt
923915 | MatchingMinimumWeak (Bound Scientific) (Bound Scientific)
916+ -- ^ producer declares a minimum numeric value ($1), consumer declares a weaker (lower) limit ($2)
924917 | NoMatchingMultipleOf Scientific
918+ -- ^ producer declares that the numeric value must be a multiple of $1, consumer doesn't
925919 | MatchingMultipleOfWeak Scientific Scientific
920+ -- ^ producer declares that the numeric value must be a multiple of $1, consumer declares a weaker condition (multiple of $2)
926921 | NoMatchingFormat Format
922+ -- ^ producer declares a string/number format, consumer declares none or a different format (TODO: improve via regex #32)
927923 | NoMatchingMaxLength Integer
924+ -- ^ producer declares a maximum length of the string ($1), consumer doesn't.
928925 | MatchingMaxLengthWeak Integer Integer
926+ -- ^ producer declares a maximum length of the string ($1), consumer declares a weaker (higher) limit ($2)
929927 | NoMatchingMinLength Integer
928+ -- ^ producer declares a minimum length of the string ($1), consumer doesn't.
930929 | MatchingMinLengthWeak Integer Integer
930+ -- ^ producer declares a minimum length of the string ($1), consumer declares a weaker (lower) limit ($2)
931931 | NoMatchingPattern Pattern
932+ -- ^ producer declares the string value must matrix a regex ($1), consumer doesn't declare or declares different regex (TODO: #32)
932933 | NoMatchingItems
934+ -- ^ producer declares the items of an array must satisfy some condition, consumer doesn't
933935 | NoMatchingMaxItems Integer
936+ -- ^ producer declares a maximum length of the array ($1), consumer doesn't.
934937 | MatchingMaxItemsWeak Integer Integer
938+ -- ^ producer declares a maximum length of the array ($1), consumer declares a weaker (higher) limit ($2)
935939 | NoMatchingMinItems Integer
940+ -- ^ producer declares a minimum length of the array ($1), consumer doesn't.
936941 | MatchingMinItemsWeak Integer Integer
942+ -- ^ producer declares a minimum length of the array ($1), consumer declares a weaker (lower) limit ($2)
937943 | NoMatchingUniqueItems
944+ -- ^ producer declares that items must be unique, consumer doesn't
938945 | NoMatchingProperties
946+ -- ^ producer declares the properties of an object must satisfy some condition, consumer doesn't
939947 | UnexpectedProperty Text
948+ -- ^ producer allows a property that is not allowed in the consumer
940949 | PropertyNowRequired Text
950+ -- ^ consumer requires a property that is not required/allowed in the consumer
941951 | NoAdditionalProperties
952+ -- ^ producer allows additional properties, consumer doesn't
942953 | NoMatchingMaxProperties Integer
954+ -- ^ producer declares a maximum number of properties in the object ($1), consumer doesn't.
943955 | MatchingMaxPropertiesWeak Integer Integer
956+ -- ^ producer declares a maximum number of properties in the object ($1), consumer declares a weaker (higher) limit ($2)
944957 | NoMatchingMinProperties Integer
958+ -- ^ producer declares a minimum number of properties in the object ($1), consumer doesn't.
945959 | MatchingMinPropertiesWeak Integer Integer
960+ -- ^ producer declares a minimum number of properties in the object ($1), consumer declares a weaker (lower) limit ($2)
946961 | NoMatchingCondition [SomeCondition]
962+ -- ^ consumer declares that the value must satisfy a disjunction of some conditions, but producer's requirements couldn't be matched against any single one of them (TODO: split heuristic #71)
947963 | NoContradiction
964+ -- ^ consumer indicates that values of this type are now allowed, but the producer does not do so (currently we only check immediate contradictions, c.f. #70)
948965 deriving stock (Eq, Ord, Show)
949966 issueIsUnsupported _ = False
950967
951968instance Issuable 'SchemaLevel where
952969 data Issue 'SchemaLevel
953970 = NotSupported Text
971+ -- ^ Some (openapi-supported) feature that we do not support was encountered in the schema
954972 | InvalidSchema Text
973+ -- ^ The schema is actually invalid
955974 deriving stock (Eq, Ord, Show)
956975 issueIsUnsupported _ = True
957976