Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sapien purus, congue a tincidunt non, mollis vitae diam. Fusce pharetra massa interdum nisl ultrices mattis. Cras eget est ultricies magna auctor condimentum. Phasellus sed elit erat, a ultricies arcu. Proin vitae volutpat ante. Quisque porta tempor elit, non aliquam tortor sodales nec. Sed imperdiet metus sed orci adipiscing faucibus. Nulla facilisi. Nulla massa tortor, dapibus a vehicula vel, cursus vel mi. Integer sed lacus velit. Etiam dignissim varius turpis ut ullamcorper. Integer lobortis imperdiet dui, ut porta nulla interdum ac. Nulla neque lorem, bibendum et venenatis a, convallis in arcu. In sagittis neque ac mauris venenatis id elementum elit lacinia. Phasellus porttitor turpis eu ipsum pharetra eleifend. Integer ac magna sit amet mi luctus scelerisque at a odio. Quisque sed mi nibh, ac pretium felis. Nunc congue sapien sit amet ipsum elementum ac euismod justo mollis. Etiam dictum elementum libero sed sagittis.
Test properties follows these patterns:
// connector configuration
connector.{$property.name}="some value"
connector.connectionUrl="jdbc:mysql://localhost/database"
// testsuite configuration
testsuite.{$property.name}="some value"
testsuite.bundleJar=System.getProperty("bundleJar")
// DataProvider configuration
i{$iteration}.{$test.name}.{$oclass.name}.${attribute.name}="some value"
i0.Create.__ACCOUNT__.DEPARTMENT="some value"
| Note: |
When defining properties, case sensitivity is important. The property property.name is derived from the setXYZ() method, which is typically inside the FooConnectorConfiguration class. |
Property values are evaluated during the initial parsing of the property files. The only exception is if either the Lazy.random()or Lazy.get() static util methods, which specify lazy evaluation, are used. If lazy evaluation is specified, a property value is not evaluated until the property is requested.
When a property value is recursively found, it is stored as the value of the property that was initially looked up. For instance, test looks for connector.i1.wrong.login and recursively finds the value of wrong.login. This value will also be stored for connector.i1.wrong.login. The next time test looks for the original property ( connector.i1.wrong...), its value will be returned immediately.
Any Java type can be used. (For more information, see standard imports.) If additional types are needed, these can be imported.
Default value definitions for property types are:
Tstring = Lazy.random("AAAAA##")
Tinteger= Lazy.random("##", Integer.class)
Tint= Lazy.random("##", Integer.class)
Tlong= Lazy.random("#####", Long.class)
// for full list of default values see /framework/contract-tests/src/bootstrap.groovy
Properties that have not been defined are assigned default values by GroovyDataProvider. For example, the test looks for the undefined property i0.Create.__ACCOUNT__.DEPARTMENT as follows:
There are no macros used in the new Groovy Contract tests, however, if you would like to transfer your old configuration, a Translation table to Groovy is available.
After it is compiled, the path to the connector distribution JAR file is ${project.name}/dist.
Use the System.getProperty() call to get the bundleJar system property that is set by ant.
testsuite.bundleJar=System.getProperty("bundleJar")
// bundleJar System property is
// set by ant to the current connector
connector.${property.name}=${value}
The following table represents two equivalent forms of defining connector properties. In most cases the option on the right is favored.
// example configuration of database table connector
// for MySQL with sample values
connector.host="localhost"
connector.login="login"
connector.password="password"
connector.port="3306"
connector.driver="com.mysql.jdbc.Driver"
connector.usermodel="modeluser"
|
// example configuration of database table connector
// for MySQL with sample values
connector {
host="localhost"
login="login"
password="password"
port="3306"
driver="com.mysql.jdbc.Driver"
usermodel="modeluser"
}
// connector
|
| Note: The prefix tree should be unique in the whole configuration file (in this case only one construct connector { ... } ) is present. | |
There are two classes of default values:
/*
* Default data values for iterative types
*/
Tstring = Lazy.random("AAAAA##")
Tinteger = Lazy.random("##", Integer.class)
Tint = Lazy.random("##", Integer.class)
Tlong = Lazy.random("#####", Long.class)
Tbiginteger = Lazy.random("#####", java.math.BigInteger.class)
Tfloat = Lazy.random("#####\\.##", Float.class)
Tdouble=Lazy.random("#####\\.##", Double.class)
Tbigdecimal=Lazy.random("#####\\.##", java.math.BigDecimal.class)
Tboolean=false
Tbytearray=Lazy.random(".............", byte[].class)
Tcharacter=Lazy.random(".", Character.class)
//Default data for multivalue attributes of common types
multi.Tstring=[Lazy.random("AAAAA##"), Lazy.random("AAAAA##")]
multi.Tinteger=[Lazy.random("##",Integer.class), Lazy.random("##", Integer.class)]
multi.Tlong=[Lazy.random("#####", Long.class), Lazy.random("#####", Long.class)]
multi.Tbiginteger=[Lazy.random("#####", java.math.BigInteger.class), Lazy.random("#####", java.math.BigInteger.class)]
multi.Tfloat=[Lazy.random("#####\\.##", Float.class), Lazy.random("#####\\.##", Float.class)]
multi.Tdouble=[Lazy.random("#####\\.##", Double.class), Lazy.random("#####\\.##", Double.class)]
multi.Tbigdecimal=[Lazy.random("#####\\.##", java.math.BigDecimal.class), Lazy.random("#####\\.##", java.math.BigDecimal.class)]
multi.Tboolean=[false, false]
multi.Tbytearray=[Lazy.random(".............", byte[].class), Lazy.random(".............", byte[].class)]
multi.Tcharacter = [Lazy.random(".", Character.class), Lazy.random(".", Character.class)]
//:~ default values
Authenticate tests in method testRun() need to know the attribute name, that contains the username. The username is later used to test authentication. The generic form of mandatory test property is:
import org.identityconnectors.contract.data.groovy.Lazy
testsuite.Authentication.
${OBJECT_CLASS}
.username = Lazy.get("i0.Authentication.
${OBJECT_CLASS}
.
${USERNAME_ATTR_NAME}
")
For example in databasetable connector we use the following setting for object class ACCOUNT and username attribute: testsuite.Authentication.__ACCOUNT__.username = Lazy.get("i0.Authentication.__ACCOUNT__.__NAME__")
// Connector WRONG configuration for ValidateApiOpTests
testsuite.Validate.invalidConfig = [
[ property1 : "invalidValue1" ],
[ property2 : "invalidValue2" ],
[ property3 : "invalidValue3", property4 : "invalidValue4" ]
// don't put more than 1 property per map
]
Validate test property explained -- testsuite.Validate.invalidConfig contains a list of maps. The test procedure is the following: (1) choose a map from the list, (2) get the default connector configuration (defined by connector.*) and override the attributes that are given on the list. (3) perform Validate operation on connector. (4) repeat from step 1. with the next map from the list.
Best practice --
// Connector WRONG configuration for TestApiOpTests
testsuite.Test.invalidConfig = [
[ attribute1 : "invalidValue1" ],
[ attribute2 : "invalidValue2" ],
[ attribute3 : "invalidValue3", attribute4 : "invalidValue4" ]
// don't put more than 1 property per map
]
The layout of testsuite.Test.invalidConfig property is the same as for ValidateApiOpTests, however it has a different meaning.
Best practice --
// Example properties for ScriptOnResource test
// Parameters required to construct ScriptContext object
testsuite.ScriptOnResource.language="Groovy"
testsuite.ScriptOnResource.script="script text"
/*
// alternative: -- good for embedding scripts as a block:
testsuite.ScriptOnResource.script='''
multi line
script text
'''
*/
testsuite.ScriptOnResource.arguments=[
arg1: "value1",
arg2: "22.5"}
]//map
// Expected return value of ScriptOnResource#runScriptOnResource method:
// use suitable macro depending on what kind of object is expected
testsuite.ScriptOnResource.result=SomeObject
testsuite.ScriptOnResource.RUN_AS_USER="user"
testsuite.ScriptOnResource.RUN_WITH_PASSWORD="password"
i{$identityNumber}.{$test.name}.{$oclass.name}.${attribute.name}=some value
// First created account by CreateApiOpTests will have FIRSTNAME attribute equal to FOO
i0.Create.__ACCOUNT__.FIRSTNAME="FOO"
// All accounts in SearchApiOpTests will have a LASTNAME attribute equal to BAR
Search.__ACCOUNT__.LASTNAME="BAR"
// All accounts in all tests will have PHONE attribute equal to 5-digit random values
__ACCOUNT__.PHONE=Lazy.random("######")
${attribute.name}=${value}
// old value
modified.${attribute.name}=${value}
// new value
added.${attribute.name}=${value}
// new value added to a multivalue property (for example: list)
// Example update LASTNAME attribute with value "sellers":
modified.LASTNAME="sellers"
// if you don't want to supply a new value for update, set it to the ObjectNotFoundException exception
modified.__NAME__=
ObjectNotFoundException()
// means that value is not supplied
Case insensitive search tests are enabled by default, optional property testsuite.Search.disable.caseinsensitive is used for explicit setting.
Connector developer should make his/her choice, if the resource for the connector is case sensitive and set the tests appropriately.
/* USAGE */
testsuite.Search.disable.caseinsensitive = true // connector is case sensitive
testsuite.Search.disable.caseinsensitive = false // otherwise
During the search contract test all the objects which are stored in the resource before the test are retrieved (due to null filter search test) and later then the test checks that are still present and unchanged (since the test does not change them). However, in some cases changes made to different objects may affect already existing objects and their attributes. For this reason the connector developer may choose not to compare these objects as a whole (ConnectorObject) and rather compare them by Uids only.
By default the whole ConnectorObject is compared.
/* USAGE */
testsuite.Search.compareExistingObjectsByUidOnly = true // compare existing objects by Uid only
testsuite.Search.compareExistingObjectsByUidOnly = false // default
testsuite.Multi.skip.lockout=true
// Long values
testsuite.Multi.__DISABLE_DATE__ = 123L
testsuite.Multi.modified.__DISABLE_DATE__ = 456L
In case of missing property definition default values are used (current timestamp, and 1/1/1970).