mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-17 20:41:49 +03:00
da8f6981d4
Fixes https://github.com/hasura/graphql-engine-mono/issues/712 Main point of interest: the `Hasura.SQL.Backend` module. This PR creates an `Exists` type indexed by indexed type and packed constraint while hiding all of its complexity by not exporting the constructor. Existential constructors/types which are no longer (directly) existential: - [X] BackendSourceInfo :: BackendSourceInfo - [x] BackendSourceMetadata :: BackendSourceMetadata - [x] MOSourceObjId :: MetadatObjId - [x] SOSourceObj :: SchemaObjId - [x] RFDB :: RootField - [x] LQP :: LiveQueryPlan - [x] ExecutionStep :: ExecStepDB This PR also removes ALL usages of `Typeable.cast` from our codebase. We still need to derive `Typeable` in a few places in order to be able to derive `Data` in one place. I have not dug deeper to see why this is needed. GitOrigin-RevId: bb47e957192e4bb0af4c4116aee7bb92f7983445
475 lines
14 KiB
Haskell
475 lines
14 KiB
Haskell
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
|
|
|
-- | This module generates a random 'Metadata' object, using a number of
|
|
-- 'Arbitrary' instances. This is used by the QuickCheck-based testing suite.
|
|
-- This module is not used by the graphql-engine library itself, and we may wish
|
|
-- to relocate it, for instance to Hasura.Generator.
|
|
|
|
module Hasura.RQL.DDL.Metadata.Generator
|
|
(genMetadata)
|
|
where
|
|
|
|
import Hasura.Prelude
|
|
|
|
import qualified Data.Aeson as J
|
|
import qualified Data.HashMap.Strict as Map
|
|
import qualified Data.HashMap.Strict.InsOrd as OM
|
|
import qualified Data.HashSet.InsOrd as SetIns
|
|
import qualified Data.Text as T
|
|
import qualified Data.Vector as V
|
|
import qualified Language.GraphQL.Draft.Parser as G
|
|
import qualified Language.GraphQL.Draft.Syntax as G
|
|
import qualified Language.Haskell.TH.Syntax as TH
|
|
import qualified Network.URI as N
|
|
import qualified System.Cron.Parser as Cr
|
|
|
|
import Data.List.Extended (duplicates)
|
|
import Data.Scientific
|
|
import System.Cron.Types
|
|
import Test.QuickCheck
|
|
import Test.QuickCheck.Instances.Semigroup ()
|
|
import Test.QuickCheck.Instances.Time ()
|
|
import Test.QuickCheck.Instances.UnorderedContainers ()
|
|
|
|
import Hasura.RQL.DDL.Headers
|
|
import Hasura.RQL.DDL.Metadata.Types
|
|
import Hasura.RQL.Types
|
|
|
|
|
|
genMetadata :: Gen Metadata
|
|
genMetadata =
|
|
Metadata
|
|
<$> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
<*> arbitrary
|
|
|
|
instance (Arbitrary k, Eq k, Hashable k, Arbitrary v) => Arbitrary (InsOrdHashMap k v) where
|
|
arbitrary = OM.fromList <$> arbitrary
|
|
|
|
instance (Arbitrary a, Eq a, Hashable a) => Arbitrary (SetIns.InsOrdHashSet a) where
|
|
arbitrary = SetIns.fromList <$> arbitrary
|
|
|
|
instance Arbitrary G.Name where
|
|
arbitrary = G.unsafeMkName . T.pack <$> listOf1 (elements ['a'..'z'])
|
|
|
|
instance Arbitrary MetadataVersion where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (FunctionMetadata b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (SourceMetadata b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary FunctionPermissionMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary TableCustomRootFields where
|
|
arbitrary = uniqueRootFields
|
|
where
|
|
uniqueRootFields = do
|
|
(a, b, c, d, e, f, g, h, i) <- arbitrary
|
|
if null $ duplicates [a, b, c, d, e, f, g, h, i] then
|
|
pure $ TableCustomRootFields a b c d e f g h i
|
|
else uniqueRootFields
|
|
|
|
instance (Backend b) => Arbitrary (TableConfig b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a, Backend b) => Arbitrary (RelUsing b a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (RelDef a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary InsertOrder where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (RelManualConfig b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (ObjRelUsingChoice b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (ArrRelUsingFKeyOn b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (PermDef a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary AddInheritedRole where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (ComputedFieldDefinition b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (ComputedFieldMetadata b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary Scientific where
|
|
arbitrary = ((fromRational . toRational) :: Int -> Scientific) <$> arbitrary
|
|
|
|
instance Arbitrary J.Value where
|
|
arbitrary = sized sizedArbitraryValue
|
|
where
|
|
sizedArbitraryValue n
|
|
| n <= 0 = oneof [pure J.Null, boolean, number, string]
|
|
| otherwise = resize n' $ oneof [pure J.Null, boolean, number, string, array, object']
|
|
where
|
|
n' = n `div` 2
|
|
boolean = J.Bool <$> arbitrary
|
|
number = J.Number <$> arbitrary
|
|
string = J.String <$> arbitrary
|
|
array = J.Array . V.fromList <$> arbitrary
|
|
object' = J.Object <$> arbitrary
|
|
|
|
instance Arbitrary ColExp where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (GExists b ColExp) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (GBoolExp b ColExp) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (BoolExp b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (PermColSpec b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (InsPerm b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (SelPerm b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (UpdPerm b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (DelPerm b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary SubscribeColumns where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary SubscribeOpSpec where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary TriggerOpsDef where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RetryConf where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary HeaderValue where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary HeaderConf where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary EventTriggerConf where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Backend b) => Arbitrary (TableMetadata b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary FunctionConfig where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary FunctionExposedAs where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary TrackFunctionV2 where
|
|
arbitrary = genericArbitrary
|
|
|
|
-- FIXME:- URI type do not have Arbitrary class implemented.
|
|
-- For time being a singe URI value is generated every time
|
|
instance Arbitrary N.URI where
|
|
arbitrary = pure $ N.URI "http:" (Just $ N.URIAuth "" "localhost" ":8080" ) "/path" "" ""
|
|
|
|
instance Arbitrary RemoteSchemaDef where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary AddRemoteSchemaQuery where
|
|
arbitrary = genericArbitrary
|
|
|
|
-- FIXME:- The GraphQL AST has 'Gen' by Hedgehog testing package which lacks the
|
|
-- 'Arbitrary' class implementation. For time being, a single query is generated every time.
|
|
instance Arbitrary GQLQueryWithText where
|
|
arbitrary = pure $ GQLQueryWithText ( "query {author {id name}}"
|
|
, GQLQuery simpleQuery
|
|
)
|
|
where
|
|
simpleQuery = $(either (fail . T.unpack) TH.lift $ G.parseExecutableDoc "query {author {id name}}")
|
|
|
|
instance Arbitrary ListedQuery where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary CollectionDef where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary CreateCollection where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary CollectionReq where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary query => Arbitrary (EndpointMetadata query) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary query => Arbitrary (EndpointDef query) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary QueryReference where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.Description where
|
|
arbitrary = G.Description <$> arbitrary
|
|
|
|
instance Arbitrary G.Nullability where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.GType where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.EnumValue where
|
|
arbitrary = G.EnumValue <$> arbitrary
|
|
|
|
instance Arbitrary InputObjectTypeName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary InputObjectFieldName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary GraphQLType where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary InputObjectFieldDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary InputObjectTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RelType where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RelationshipName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ObjectFieldName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a, Arbitrary b) => Arbitrary (TypeRelationship a b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ObjectTypeName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (ObjectFieldDefinition a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (ObjectTypeDefinition a b c) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ScalarTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary EnumTypeName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary EnumValueDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary EnumTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary CustomTypes where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ArgumentName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (ArgumentDefinition a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ActionMutationKind where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ActionType where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a, Arbitrary b) => Arbitrary (ActionDefinition a b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ActionName where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ActionPermissionMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ActionMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
deriving instance Arbitrary RemoteArguments
|
|
|
|
instance Arbitrary FieldCall where
|
|
arbitrary = genericArbitrary
|
|
|
|
deriving instance Arbitrary RemoteFields
|
|
|
|
instance Arbitrary RemoteRelationshipDef where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RemoteRelationshipMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary CronTriggerMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary STRetryConf where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary NonNegativeDiffTime where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary CronSchedule where
|
|
arbitrary = elements sampleCronSchedules
|
|
|
|
instance Arbitrary (G.Directive Void) where
|
|
arbitrary = elements sampleDirectives
|
|
|
|
instance Arbitrary (G.Value Void) where
|
|
arbitrary = elements sampleGraphQLValues
|
|
|
|
instance Arbitrary (G.Value G.Name) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (G.FieldDefinition a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.ScalarTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.InputValueDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (G.InputObjectTypeDefinition a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a) => Arbitrary (G.ObjectTypeDefinition a) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.RootOperationTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.OperationType where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.UnionTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.EnumValueDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.EnumTypeDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a, Arbitrary b) => Arbitrary (G.InterfaceTypeDefinition a b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance (Arbitrary a, Arbitrary b) => Arbitrary (G.TypeDefinition a b) where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.TypeSystemDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.SchemaDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary G.SchemaDocument where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RemoteSchemaPermissionDefinition where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RemoteSchemaPermissionMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RemoteSchemaMetadata where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary MetadataResourceVersion where
|
|
arbitrary = MetadataResourceVersion <$> arbitrary
|
|
|
|
sampleCronSchedules :: [CronSchedule]
|
|
sampleCronSchedules = rights $ map Cr.parseCronSchedule
|
|
[ "* * * * *"
|
|
-- every minute
|
|
, "5 * * * *"
|
|
-- every hour at the 5th minute
|
|
, "\5 * * * *"
|
|
-- every 5 minutes
|
|
, "* 5 * * *"
|
|
-- every minute of the 5th hour of the day
|
|
, "5 5 * * *"
|
|
-- fifth minute of the fifth hour every day
|
|
, "0 0 5 * *"
|
|
-- 00:00 of the 5th day of every month
|
|
, "0 0 1 1 *"
|
|
-- 00:00 of 1st of January
|
|
, "0 0 * * 0"
|
|
-- Every sunday at 00:00
|
|
]
|
|
|
|
-- Hardcoding the values of `sampleDirectives` and `sampleGraphQLValues` because
|
|
-- there's no `Arbitrary` instance of `Void`
|
|
sampleDirectives :: [G.Directive Void]
|
|
sampleDirectives = [ (G.Directive $$(G.litName "directive_1") mempty)
|
|
, (G.Directive $$(G.litName "directive_2") $
|
|
(Map.singleton $$(G.litName "value") (G.VInt 1)))
|
|
, (G.Directive $$(G.litName "directive_3") $
|
|
(Map.singleton $$(G.litName "value") (G.VBoolean True)))
|
|
]
|
|
|
|
sampleGraphQLValues :: [G.Value Void]
|
|
sampleGraphQLValues = [ G.VInt 1
|
|
, G.VNull
|
|
, G.VFloat 2.5
|
|
, G.VString "article"
|
|
, G.VBoolean True
|
|
]
|
|
|
|
instance Arbitrary MetricsConfig where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary ApiLimit where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary DepthLimit where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RateLimit where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary RateLimitConfig where
|
|
arbitrary = genericArbitrary
|
|
|
|
instance Arbitrary UniqueParamConfig where
|
|
arbitrary = elements sampleUniqueParamConfigs
|
|
|
|
sampleUniqueParamConfigs :: [UniqueParamConfig]
|
|
sampleUniqueParamConfigs = [ UPCIpAddress
|
|
, UPCSessionVar ["x-hasura-user-id"]
|
|
, UPCSessionVar ["x-hasura-user-id", "x-hasura-team-id"]
|
|
, UPCSessionVar ["x-hasura-user-id", "x-hasura-team-id", "x-hasura-org-id"]
|
|
]
|