Documentation ¶
Index ¶
- func SpecificationIdentifierFromSchemaVersion(schemaVersion string) (string, error)
- type ConditionEnum
- type Conditionality
- type ConditionalityChecker
- type Context
- type ContextAccessor
- type Expect
- type Input
- type Manifest
- type Match
- type MatchType
- type Permission
- type PermissionSet
- func (set *PermissionSet) Add(s string) bool
- func (set *PermissionSet) AddPermissions(ss []string)
- func (set *PermissionSet) Get(s string) bool
- func (set *PermissionSet) GetName() string
- func (set *PermissionSet) GetPermissions() []string
- func (set *PermissionSet) IsSubset(sub *PermissionSet) bool
- func (set *PermissionSet) Remove(s string)
- func (set *PermissionSet) SetName(s string)
- func (set *PermissionSet) Union(u *PermissionSet) *PermissionSet
- type Rule
- type Specification
- type TestCase
- func (t *TestCase) ApplyContext() (*http.Request, error)
- func (t *TestCase) ApplyExpects(res *http.Response, rulectx *Context) (bool, error)
- func (t *TestCase) ApplyInput(rulectx *Context) (*http.Request, error)
- func (t *TestCase) Dump(print bool)
- func (t *TestCase) GetExcludedPermissions() []string
- func (t *TestCase) GetIncludedPermission() []string
- func (t *TestCase) GetPermissions() (included, excluded []string)
- func (t *TestCase) Prepare(ctx *Context) (*http.Request, error)
- func (t *TestCase) Validate(resp *http.Response, rulectx *Context) (bool, error)
- type TestCaseExecutor
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SpecificationIdentifierFromSchemaVersion ¶
SpecificationIdentifierFromSchemaVersion - returns specification identifier for given schema version URL, or nil when there is no match.
Types ¶
type ConditionEnum ¶
type ConditionEnum int
ConditionEnum models endpoint conditionality based on: Account and Transaction API Specification - v3.0 - Section 4 Endpoints https://openbanking.atlassian.net/wiki/spaces/DZ/pages/642090641/Account+and+Transaction+API+Specification+-+v3.0#AccountandTransactionAPISpecification-v3.0-Endpoints Also see "Categorisation of Implementation Requirements" section of the following document https://openbanking.atlassian.net/wiki/spaces/DZ/pages/641992418/Read+Write+Data+API+Specification+-+v3.0#Read/WriteDataAPISpecification-v3.0-CategorisationofImplementationRequirements
const ( // Mandatory - required Mandatory ConditionEnum = iota // Conditional on a regulartory requirement Conditional // Optional at the implementors discretion Optional // UndefinedCondition - UndefinedCondition )
func GetConditionality ¶
func GetConditionality(method, endpoint string, specification string) (ConditionEnum, error)
GetConditionality - returns and indicator in the following for of the method/endpoint conditionality model.Mandatory - endpoint is Mandatory model.Conditional - endpoint is conditional model.Optional - endpoint is optional model.UndefineCondition - we don't recognise the endpoint
type Conditionality ¶
type Conditionality struct { Condition ConditionEnum `json:"condition,omitempty"` Method string `json:"method,omitempty"` Endpoint string `json:"endpoint,omitempty"` }
Conditionality - capture the conditionality of a method/endpoint
func GetEndpointConditionality ¶
func GetEndpointConditionality(specification string) []Conditionality
GetEndpointConditionality - get a clone of `endpointConditionality` array for given specification identifier
type ConditionalityChecker ¶
type ConditionalityChecker interface { IsPresent(method, endpoint string, specification string) (bool, error) IsOptional(method, endpoint string, specification string) (bool, error) IsMandatory(method, endpoint string, specification string) (bool, error) IsConditional(method, endpoint string, specification string) (bool, error) MissingMandatory(endpoints []Input, specification string) ([]Input, error) }
ConditionalityChecker - interface to provide loose coupling between endpoint conditionality checks and invoking code
func NewConditionalityChecker ¶
func NewConditionalityChecker() ConditionalityChecker
NewConditionalityChecker - returns implementation of ConditionalityChecker interface for checking endpoint conditionality
type Context ¶
type Context map[string]interface{}
Context is intended to handle two types of object and make them available to various parts of the suite including testcases. The first set are objects created as a result of the discovery phase, which capture discovery model information like endpoints and conditional implementation indicators. The other set of data is information passed between a sequeuence of test cases, for example AccountId - extracted from the output of one testcase (/Accounts) and fed in as part of the input of another testcase for example (/Accounts/{AccountId}/transactions}
type ContextAccessor ¶
ContextAccessor - Manages access to matches for Put and Get value operations on a context
func (*ContextAccessor) GetValues ¶
func (c *ContextAccessor) GetValues(tc *TestCase, ctx *Context) error
GetValues - checks for match elements in the contextGet section For each valid element there need to be a ContextName which is the name of the variable in the context we're trying to retrieve Once we have retrieved a context variable, we need to know what to do with it. Current we can ReplaceEndpoint - so basically do a string replace on our testcase endpoint which for example allows us to replace {AccountId} with a real account id
func (*ContextAccessor) PutValues ¶
func (c *ContextAccessor) PutValues(tc *TestCase, ctx *Context) (string, error)
PutValues is used by the 'contextPut' directive and essentially collects a set of matches whose purpose is To select values to put in a context. All the matches in this section must have a name (of the target context variable), a description (so if things go wrong we can accurately report) and an operation which results in the a selection which is copied into the context variable Note: the initial interation of this will just implement the JSON pattern/field matcher
type Expect ¶
type Expect struct { StatusCode int `json:"status-code,omitempty"` // Http response code SchemaValidation bool `json:"schema-validation,omitempty"` // Flag to indicate if we need schema validation - // provides the ability to switch off schema validation Matches []Match `json:"matches,omitempty"` // An array of zero or more match items which must be 'passed' for the testcase to succeed ContextPut ContextAccessor `json:"contextPut,omitempty"` // allows storing of test response fragments in context variables }
Expect defines a structure for expressing testcase result expectations.
type Input ¶
type Input struct { Method string `json:"method,omitempty"` // http Method that this test case uses Endpoint string `json:"endpoint,omitempty"` // resource endpoint where the http object needs to be sent to get a response ContextGet ContextAccessor `json:"contextGet,omitempty"` // Allows retrieval of context variables an input parameters }
Input defines the content of the http request object used to execute the test case Input is built up typically from the openapi/swagger definition of the method/endpoint for a particualar specification. Additional properties/fields/headers can be added or change in order to setup the http request object of the specific test case. Once setup correctly,the testcase gives the http request object to the parent Rule which determine how to execute the requestion object. On execution an http response object is received and passed back to the testcase for validation using the Expects object.
type Manifest ¶
type Manifest struct { Context string `json:"@context"` // JSONLD contest reference ID string `json:"@id"` // JSONLD ID reference Type string `json:"@type"` // JSONLD Type reference Name string `json:"name"` // Name of the manifiest Description string `json:"description"` // Description of the Mainfest and what it contains BaseIri string `json:"baseIri"` // Base Iri Sections []Context `json:"section_contexts"` // Section specific contexts Rules []Rule `json:"rules"` // All the rules in the Manifest }
Manifest is the high level container for test suite definition It contains a list of all the rules required to be passed for conformance testing Each rule can have multiple testcases which contribute to testing that particular rule So essentially Manifest is a container
type Match ¶
type Match struct { MatchType MatchType `json:"match_type,omitempty"` // Type of Match we're doing Description string `json:"description,omitempty"` // Description of the purpose of the match ContextName string `json:"name,omitempty"` // Context variable name Header string `json:"header,omitempty"` // Header value to examine HeaderPresent string `json:"header-present,omitempty"` // Header existence check Regex string `json:"regex,omitempty"` // Regular expression to be used JSON string `json:"json,omitempty"` // Json expression to be used Value string `json:"value,omitempty"` // Value to match against (string) Numeric int64 `json:"numeric,omitempty"` //Value to match against - numeric Count int64 `json:"count,omitempty"` // Cont for JSON array match purposes BodyLength *int64 `json:"body-length,omitempty"` // Body payload length for matching ReplaceEndpoint string `json:"replaceInEndpoint,omitempty"` // allows substituion of resourceIds }
Match defines various types of response payload pattern and field checking. Match forms the basis for response validation outside of basic swagger/openapi schema validation Match is also used as the basis for field extraction and replacement which enable parameter passing between tests via the context. Match encapsulates a conditional statement that must 'match' in order to succeed. Matches can - - match a specified header field value for exact match - match a specified header field value using a regular expression - check that a specified header field exists in the response - check that a response body matches a regular expression - check that a response body has a particular json field present using json matching - check that a response body has a specific number of specified json array fields - check that a response body has a specific value of a specified json field - check that a response body has a specific json field and that the specific json field matches a regular expression - check that a response body is a specified length
func (*Match) Check ¶
Check a match function - figures out which match type we have and calls the appropraite match checking function
type Permission ¶
type Permission struct { Permission string `json:"permission,omitempty"` Endpoints []string `json:"endpoints,omitempty"` Default bool `json:"default,omitempty"` RequiredPermissions []string `json:"required_permissions,omitempty"` Optional []string `json:"optional,omitempty"` }
Permission holds endpoint permission data
func GetPermissionFromName ¶
func GetPermissionFromName(name string) Permission
GetPermissionFromName returns a permission if a matching permission name is found or and empty permission if an entry with a matching name is not found
func GetPermissionsForEndpoint ¶
func GetPermissionsForEndpoint(endpoint string) []Permission
GetPermissionsForEndpoint returns a list of permissions that are accepted by the specified endpoint no indication of whats mandatory/optional is given, you have to examine the individual permissions returned for that information if not entries are found a permission array with zero entries is returned
type PermissionSet ¶
type PermissionSet struct {
// contains filtered or unexported fields
}
PermissionSet contains a collection of permission names with the intention of using this structure to determine whether specific permissions are included in the set.
func NewPermissionSet ¶
func NewPermissionSet(name string, strPermissions []string) *PermissionSet
NewPermissionSet create a new permission set of an array of string permission names
func (*PermissionSet) Add ¶
func (set *PermissionSet) Add(s string) bool
Add a string to a PermissionSet
func (*PermissionSet) AddPermissions ¶
func (set *PermissionSet) AddPermissions(ss []string)
AddPermissions - adds permission strings from a slice
func (*PermissionSet) Get ¶
func (set *PermissionSet) Get(s string) bool
Get a permission from the PermissionSet
func (*PermissionSet) GetName ¶
func (set *PermissionSet) GetName() string
GetName returns the name associated with this permission set
func (*PermissionSet) GetPermissions ¶
func (set *PermissionSet) GetPermissions() []string
GetPermissions returns a string array of the permissions in a permissionSet
func (*PermissionSet) IsSubset ¶
func (set *PermissionSet) IsSubset(sub *PermissionSet) bool
IsSubset determines if the permissionSet passed in as a paramter is a subset of the target PermissionSet
func (*PermissionSet) Remove ¶
func (set *PermissionSet) Remove(s string)
Remove a value from the PermissionSet
func (*PermissionSet) SetName ¶
func (set *PermissionSet) SetName(s string)
SetName sets the name associated with this permission set
func (*PermissionSet) Union ¶
func (set *PermissionSet) Union(u *PermissionSet) *PermissionSet
Union returns a new PermissionSet named "union" which is the union of the receiver and parameter permissionSets
type Rule ¶
type Rule struct { ID string `json:"@id"` // JSONLD ID reference Type []string `json:"@type,omitempty"` // JSONLD type reference Name string `json:"name"` // A short meaningful name for this rule Purpose string `json:"purpose"` // The purpose of this rule Specref string `json:"specref"` // Description of area of spec/name/version/section under test Speclocation string `json:"speclocation"` // specific http reference to location in spec under test covered by this rule Tests [][]TestCase `json:"tests"` // Tests - allows for many testcases - array of arrays - to be associated with this rule Executor TestCaseExecutor // TestCaseExecutor interface allow different testcase execution strategies }
Rule - Define a specific location within a specification that is being tested Rule also identifies all the tests that must be passed in order to show that the rule implementation in conformant with the specific section in the referenced specification
func (*Rule) Execute ¶
Execute the testcase For the rule this effectively equates to sending the assembled http request from the testcase to an endpoint (typically ASPSP implemetation) and getting an http.Response The http.Request at this point will contain the fully assembled request from a testcase point of view - testcase will have likely pulled out appropriate access_tokens/permissions - rule will have the opportunited to further decorate this request before passing on
func (*Rule) GetPermissionSets ¶
GetPermissionSets returns the inclusive and exclusive permission sets required to run the tests under this rule. Initially the granulatiy of permissionSets will be set at rule level, meaning that one included set and one excluded set will cover all the testcases with a rule. In future iterations it may be desirable to have per testSequence permissionSets as this would allow a finer grained mix of negative permission testing
type Specification ¶
type Specification struct { Identifier string `json:"identifier,omitempty" validate:"required"` Name string `json:"name,omitempty" validate:"required"` URL string `json:"url,omitempty" validate:"required,url"` Version string `json:"version,omitempty" validate:"required"` SchemaVersion string `json:"schemaVersion,omitempty" validate:"required,url"` }
Specification - Represents OB API specification. Fields are from the APIReference JSON-LD schema, see: https://schema.org/APIReference URL - URL of confluence specification file. SchemaVersion - URL of OpenAPI/Swagger specification file.
func SpecificationFromSchemaVersion ¶
func SpecificationFromSchemaVersion(schemaVersion string) (Specification, error)
SpecificationFromSchemaVersion - returns specification struct for given schema version URL, or nil when there is no match.
type TestCase ¶
type TestCase struct { ID string `json:"@id,omitempty"` // JSONLD ID Reference Type []string `json:"@type,omitempty"` // JSONLD type array Name string `json:"name,omitempty"` // Name Purpose string `json:"purpose,omitempty"` // Purpose of the testcase in simple words Input Input `json:"input,omitempty"` // Input Object Context Context `json:"context,omitempty"` // Local Context Object Expect Expect `json:"expect,omitempty"` // Expected object ParentRule *Rule // Allows accessing parent Rule Request *http.Request // The request that's been generated in order to call the endpoint Header http.Header // ResponseHeader Body string // ResponseBody }
TestCase defines a test that will be run and needs to be passed as part of the conformance suite in order to determine implementation conformance to a specification. Testcase have three major sections Input:
Defines the inputs that are required by the testcase. This effectively involves preparing the http request object
Context:
Provides a link between Discovery information and the testcase
Expects:
Examines the http response to the testcase Input in order to determine if the expected conditions existing in the response and therefore the testcase has passed
func NewTestCase ¶
func NewTestCase() *TestCase
NewTestCase creates an Context thats initialised correctly with a map structure which holds the context parameters
func (*TestCase) ApplyContext ¶
ApplyContext - at the end of ApplyInputs on the testcase - we have an initial http request object ApplyContext, applys context parameters to the http object. Context parameter typically involve variables that originaled in discovery The functionality of ApplyContext will grow significantly over time.
func (*TestCase) ApplyExpects ¶
ApplyExpects runs the Expects section of the testcase to evaluate if the response from the system under test passes or fails The Expects section of a testcase can contain multiple conditions that need to be met to pass a testcase When a test fails, ApplyExpects is responsible for reporting back information about the failure, why it occured, where it occured etc.
The ApplyExpect section is also responsible for running and contextPut clauses. contextPuts are responsible for updated context variables with values selected from the test case response contextPuts will only be executed if the ApplyExpects standards match tests pass if any of the ApplyExpects match tests fail - ApplyExpects returns false and contextPuts aren't executed
func (*TestCase) ApplyInput ¶
ApplyInput - creates an HTTP request for this test case The reason why we're doing this is that a testcase behaves like an http object It produces an http.Request - which can be sent to a server It consumes and http.Response - which it uses to validate the response against "Expects" TestCase lifecycle:
Create a Testcase Object Create / retrieve the http request object Apply context information to the request object Rule - manages passing the request object from the testcase to an appropriate endpoint handler (like the proxy) Rule - receives http response from endpoint and provides it back to testcase Testcase evaluates the http response object using its 'Expects' clause Testcase passes or fails depending on the 'Expects' outcome
func (*TestCase) GetExcludedPermissions ¶
GetExcludedPermissions return a list of excluded permissions
func (*TestCase) GetIncludedPermission ¶
GetIncludedPermission returns the list of permission names that need to be included in the access token for this testcase. See permission model docs for more information
func (*TestCase) GetPermissions ¶
GetPermissions returns a list of Permission objects associated with a testcase
func (*TestCase) Prepare ¶
Prepare a Testcase for execution at and endpoint, results in a standard http request that encapsulates the testcase request as defined in the test case object with any context inputs/replacements etc applied
func (*TestCase) Validate ¶
Validate takes the http response that results as a consequence of sending the testcase http request to the endpoint implementation. Validate is responsible for checking the http status code and running the set of 'Matches' within the 'Expect' object, to determine if all the match conditions are met - which would mean the validation passed. The context object is passed as part of the validation as its allows the match clauses to examine the request object and 'push' response variables into the context object for use in downstream test cases which are potentially part of this testcase sequence returns true - validation successful
false - validation unsuccessful error - adds detail to validation failure TODO - cater for returning multiple validation failures and explanations NOTE: Vadiate will only return false if a check fails - no checks = true