summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/variant/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--contrib/slapd-modules/variant/tests/Rules.mk23
-rw-r--r--contrib/slapd-modules/variant/tests/data/additional-config.ldif23
-rw-r--r--contrib/slapd-modules/variant/tests/data/config.ldif89
-rw-r--r--contrib/slapd-modules/variant/tests/data/hidden.ldif4
-rw-r--r--contrib/slapd-modules/variant/tests/data/test001-01-same-dn.ldif4
-rw-r--r--contrib/slapd-modules/variant/tests/data/test001-01a-same-dn.ldif4
-rw-r--r--contrib/slapd-modules/variant/tests/data/test001-02-same-attribute.ldif6
-rw-r--r--contrib/slapd-modules/variant/tests/data/test001-03-different-types.ldif4
-rw-r--r--contrib/slapd-modules/variant/tests/data/test002-01-entry.ldif16
-rw-r--r--contrib/slapd-modules/variant/tests/data/test002-02-regex.ldif7
-rw-r--r--contrib/slapd-modules/variant/tests/data/test003-out.ldif124
-rw-r--r--contrib/slapd-modules/variant/tests/data/test005-changes.ldif35
-rw-r--r--contrib/slapd-modules/variant/tests/data/test005-modify-missing.ldif4
-rw-r--r--contrib/slapd-modules/variant/tests/data/test005-out.ldif206
-rw-r--r--contrib/slapd-modules/variant/tests/data/test005-variant-missing.ldif4
-rw-r--r--contrib/slapd-modules/variant/tests/data/test006-config.ldif61
-rw-r--r--contrib/slapd-modules/variant/tests/data/test006-out.ldif151
-rw-r--r--contrib/slapd-modules/variant/tests/data/test007-out.ldif6
-rw-r--r--contrib/slapd-modules/variant/tests/data/test010-out.ldif52
-rw-r--r--contrib/slapd-modules/variant/tests/data/test011-out.ldif10
-rw-r--r--contrib/slapd-modules/variant/tests/data/test012-data.ldif13
-rw-r--r--contrib/slapd-modules/variant/tests/data/test012-out.ldif9
-rw-r--r--contrib/slapd-modules/variant/tests/data/variant.conf17
-rwxr-xr-xcontrib/slapd-modules/variant/tests/run229
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/all102
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/common.sh115
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test001-config209
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test002-add-delete113
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test003-search113
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test004-compare63
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test005-modify120
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test006-acl323
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test007-subtypes67
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test008-variant-replication194
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test009-ignored-replication227
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test010-limits99
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test011-referral169
-rwxr-xr-xcontrib/slapd-modules/variant/tests/scripts/test012-crossdb90
38 files changed, 3105 insertions, 0 deletions
diff --git a/contrib/slapd-modules/variant/tests/Rules.mk b/contrib/slapd-modules/variant/tests/Rules.mk
new file mode 100644
index 0000000..c25c1d2
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/Rules.mk
@@ -0,0 +1,23 @@
+sp := $(sp).x
+dirstack_$(sp) := $(d)
+d := $(dir)
+
+.PHONY: test
+
+CLEAN += clients servers tests/progs tests/schema tests/testdata tests/testrun
+
+test: all clients servers tests/progs
+
+test:
+ cd tests; \
+ SRCDIR=$(abspath $(LDAP_SRC)) \
+ LDAP_BUILD=$(abspath $(LDAP_BUILD)) \
+ TOPDIR=$(abspath $(SRCDIR)) \
+ LIBTOOL=$(abspath $(LIBTOOL)) \
+ $(abspath $(SRCDIR))/tests/run all
+
+servers clients tests/progs:
+ ln -s $(abspath $(LDAP_BUILD))/$@ $@
+
+d := $(dirstack_$(sp))
+sp := $(basename $(sp))
diff --git a/contrib/slapd-modules/variant/tests/data/additional-config.ldif b/contrib/slapd-modules/variant/tests/data/additional-config.ldif
new file mode 100644
index 0000000..6a286fe
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/additional-config.ldif
@@ -0,0 +1,23 @@
+dn: name={4}test002,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
+
+dn: name=attribute 1,name={4}test002,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantVariantAttribute: cn
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: dc=example,dc=com
+
+dn: name=attribute 2,name={4}test002,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantVariantAttribute: pager
+olcVariantAlternativeAttribute: telephonenumber
+olcVariantAlternativeEntry: dc=example,dc=com
+
+dn: name={0}attribute 1,name={4}test002,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: modify
+replace: olcVariantVariantAttribute
+olcVariantVariantAttribute: description
diff --git a/contrib/slapd-modules/variant/tests/data/config.ldif b/contrib/slapd-modules/variant/tests/data/config.ldif
new file mode 100644
index 0000000..6e323b9
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/config.ldif
@@ -0,0 +1,89 @@
+dn: olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectClass: olcOverlayConfig
+objectclass: olcVariantConfig
+
+dn: olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: modify
+replace: olcVariantPassReplication
+olcVariantPassReplication: TRUE
+
+dn: name={0}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: ou=People,dc=example,dc=com
+
+# a basic variant
+dn: olcVariantVariantAttribute=description,name={0}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: dc=example,dc=com
+
+# a nonexistent alternate
+dn: olcVariantVariantAttribute=seealso,name={0}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: seealso
+olcVariantAlternativeEntry: ou=Societies,dc=example,dc=com
+
+dn: name={1}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: ou=Groups,dc=example,dc=com
+
+# recursive retrieval is not done
+dn: olcVariantVariantAttribute=description,name={1}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: ou=People,dc=example,dc=com
+
+# a variant taking data from a different attribute (after the changes below)
+dn: olcVariantVariantAttribute=st,name={1}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: st
+olcVariantAlternativeEntry: cn=Manager,dc=example,dc=com
+
+# configuration changes
+dn: olcVariantVariantAttribute={1}st,name={1}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: modify
+replace: olcVariantAlternativeAttribute
+olcVariantAlternativeAttribute: ou
+-
+replace: olcVariantAlternativeEntry
+olcVariantAlternativeEntry: ou=Alumni Association,ou=People,dc=example,dc=com
+-
+
+# a regex variant
+dn: name={2}regex,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantRegex
+olcVariantEntryRegex: (.*),(ou=.*technology.*)(,)dc=example,dc=com
+
+dn: olcVariantVariantAttribute=ou,name={2}regex,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttributePattern
+olcVariantAlternativeAttribute: ou
+olcVariantAlternativeEntryPattern: $2$3dc=example$3dc=com
+
+# Duplicate description into title
+dn: olcVariantVariantAttribute=title,name={2}regex,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttributePattern
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntryPattern: $0
+
+# everything
+dn: name={3}regex,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantRegex
+olcVariantEntryRegex: .*
+
+dn: olcVariantVariantAttribute=l,name={3}regex,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttributePattern
+olcVariantAlternativeAttribute: l
+olcVariantAlternativeEntryPattern: dc=example,dc=com
+
diff --git a/contrib/slapd-modules/variant/tests/data/hidden.ldif b/contrib/slapd-modules/variant/tests/data/hidden.ldif
new file mode 100644
index 0000000..d219746
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/hidden.ldif
@@ -0,0 +1,4 @@
+dn: ou=Groups,dc=example,dc=com
+changetype: modify
+add: description
+description: This is hidden by the overlay config
diff --git a/contrib/slapd-modules/variant/tests/data/test001-01-same-dn.ldif b/contrib/slapd-modules/variant/tests/data/test001-01-same-dn.ldif
new file mode 100644
index 0000000..880e035
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test001-01-same-dn.ldif
@@ -0,0 +1,4 @@
+dn: name=variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: ou=Groups,dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/data/test001-01a-same-dn.ldif b/contrib/slapd-modules/variant/tests/data/test001-01a-same-dn.ldif
new file mode 100644
index 0000000..0fb8b2b
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test001-01a-same-dn.ldif
@@ -0,0 +1,4 @@
+dn: name={0}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: modify
+replace: olcVariantEntry
+olcVariantEntry: ou=Groups,dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/data/test001-02-same-attribute.ldif b/contrib/slapd-modules/variant/tests/data/test001-02-same-attribute.ldif
new file mode 100644
index 0000000..8447018
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test001-02-same-attribute.ldif
@@ -0,0 +1,6 @@
+dn: olcVariantAlternativeAttribute=description,name={1}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantVariantAttribute: description
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: ou=People,dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/data/test001-03-different-types.ldif b/contrib/slapd-modules/variant/tests/data/test001-03-different-types.ldif
new file mode 100644
index 0000000..dfbde5b
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test001-03-different-types.ldif
@@ -0,0 +1,4 @@
+dn: olcVariantVariantAttribute={1}st,name={1}variant,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: modify
+replace: olcVariantAlternativeAttribute
+olcVariantAlternativeAttribute: userPassword
diff --git a/contrib/slapd-modules/variant/tests/data/test002-01-entry.ldif b/contrib/slapd-modules/variant/tests/data/test002-01-entry.ldif
new file mode 100644
index 0000000..21b5b14
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test002-01-entry.ldif
@@ -0,0 +1,16 @@
+dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
+changetype: add
+objectclass: testPerson
+cn: Gern Jensen
+sn: Jensen
+uid: gjensen
+postaladdress: ITD $ 535 W. William St $ Anytown, MI 48103
+seealso: cn=All Staff,ou=Groups,dc=example,dc=com
+drink: Coffee
+homepostaladdress: 844 Brown St. Apt. 4 $ Anytown, MI 48104
+description: Very odd
+facsimiletelephonenumber: +1 313 555 7557
+telephonenumber: +1 313 555 8343
+mail: gjensen@mailgw.example.com
+homephone: +1 313 555 8844
+testTime: 20050304001801.234Z
diff --git a/contrib/slapd-modules/variant/tests/data/test002-02-regex.ldif b/contrib/slapd-modules/variant/tests/data/test002-02-regex.ldif
new file mode 100644
index 0000000..8f0f439
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test002-02-regex.ldif
@@ -0,0 +1,7 @@
+dn: cn=Rosco P. Coltrane, ou=Information Technology Division, ou=People, dc=example,dc=com
+changetype: add
+objectclass: OpenLDAPperson
+cn: Rosco P. Coltrane
+sn: Coltrane
+uid: rosco
+title: Chief Investigator, ITD
diff --git a/contrib/slapd-modules/variant/tests/data/test003-out.ldif b/contrib/slapd-modules/variant/tests/data/test003-out.ldif
new file mode 100644
index 0000000..1c3ca5d
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test003-out.ldif
@@ -0,0 +1,124 @@
+# Test 1, list two unrelated entries
+dn: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: Mark Elliot
+cn: Mark A Elliot
+sn: Elliot
+uid: melliot
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 199 Outer Drive $ Ypsilanti, MI 48198
+homePhone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.example.com
+pager: +1 313 555 7671
+facsimileTelephoneNumber: +1 313 555 7762
+telephoneNumber: +1 313 555 4177
+
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+objectClass: OpenLDAPperson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+uid: bjorn
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+userPassword:: Ympvcm4=
+homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+description: Hiker, biker
+title: Director, Embedded Systems
+postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
+mail: bjorn@mailgw.example.com
+homePhone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimileTelephoneNumber: +1 313 555 2177
+telephoneNumber: +1 313 555 0355
+
+
+# Test 2, list some of the variant entries, checking that attributes have been populated
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+st: Alumni Association
+
+dn: ou=People,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: extensibleObject
+ou: People
+uidNumber: 0
+gidNumber: 0
+description: The Example, Inc. at Anytown
+
+dn: cn=Manager,dc=example,dc=com
+objectClass: person
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userPassword:: c2VjcmV0
+
+
+# Return $BASEDN, location is rewritten to end
+dn: dc=example,dc=com
+objectClass: top
+objectClass: organization
+objectClass: domainRelatedObject
+objectClass: dcObject
+dc: example
+st: Michigan
+o: Example, Inc.
+o: EX
+o: Ex.
+description: The Example, Inc. at Anytown
+postalAddress: Example, Inc. $ 535 W. William St. $ Anytown, MI 48109 $ US
+telephoneNumber: +1 313 555 1817
+associatedDomain: example.com
+l: Anytown, Michigan
+
+
+# Make sure only the first regex applies
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+objectClass: OpenLDAPperson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+uid: bjorn
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+userPassword:: Ympvcm4=
+homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+description: Hiker, biker
+postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
+mail: bjorn@mailgw.example.com
+homePhone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimileTelephoneNumber: +1 313 555 2177
+telephoneNumber: +1 313 555 0355
+title: Hiker, biker
+ou: Information Technology Division
+
+
+# Exercise the last regex
+dn: cn=ITD Staff,ou=Groups,dc=example,dc=com
+owner: cn=Manager,dc=example,dc=com
+description: All ITD Staff
+cn: ITD Staff
+objectClass: groupOfUniqueNames
+uniqueMember: cn=Manager,dc=example,dc=com
+uniqueMember: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=
+ example,dc=com
+uniqueMember: cn=James A Jones 2,ou=Information Technology Division,ou=People,
+ dc=example,dc=com
+uniqueMember: cn=John Doe,ou=Information Technology Division,ou=People,dc=exam
+ ple,dc=com
+l: Anytown, Michigan
+
+
+# Test 3, check filters pick up the new data
+dn: ou=Groups,dc=example,dc=com
+st: Alumni Association
+
diff --git a/contrib/slapd-modules/variant/tests/data/test005-changes.ldif b/contrib/slapd-modules/variant/tests/data/test005-changes.ldif
new file mode 100644
index 0000000..767f48a
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test005-changes.ldif
@@ -0,0 +1,35 @@
+dn: ou=People,dc=example,dc=com
+changetype: modify
+add: description
+description: Everyone's heard of them
+-
+increment: uidNumber
+uidNumber: 1
+-
+
+dn: ou=Groups,dc=example,dc=com
+changetype: modify
+add: st
+st: Alabama
+-
+
+# check regex
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+changetype: modify
+replace: description
+description: A mouthful
+-
+add: ou
+ou: The IT Crowd
+-
+
+# have the two mods merge
+dn: dc=example,dc=com
+changetype: modify
+add: l
+l: Locally
+-
+replace: st
+st: Antarctica
+-
diff --git a/contrib/slapd-modules/variant/tests/data/test005-modify-missing.ldif b/contrib/slapd-modules/variant/tests/data/test005-modify-missing.ldif
new file mode 100644
index 0000000..ce9c007
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test005-modify-missing.ldif
@@ -0,0 +1,4 @@
+dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
+changetype: modify
+replace: description
+description: Ghost
diff --git a/contrib/slapd-modules/variant/tests/data/test005-out.ldif b/contrib/slapd-modules/variant/tests/data/test005-out.ldif
new file mode 100644
index 0000000..67e441b
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test005-out.ldif
@@ -0,0 +1,206 @@
+# Test1: list entries that should have been changed by ldapmodify
+dn: dc=example,dc=com
+objectclass: top
+objectclass: organization
+objectclass: domainRelatedObject
+objectclass: dcobject
+dc: example
+l: Anytown, Michigan
+l: Locally
+o: Example, Inc.
+o: EX
+o: Ex.
+description: The Example, Inc. at Anytown
+description: Everyone's heard of them
+postaladdress: Example, Inc. $ 535 W. William St. $ Anytown, MI 48109 $ US
+telephonenumber: +1 313 555 1817
+associateddomain: example.com
+st: Antarctica
+
+dn: ou=People,dc=example,dc=com
+objectclass: organizationalUnit
+objectclass: extensibleObject
+ou: People
+uidNumber: 1
+gidNumber: 0
+description: The Example, Inc. at Anytown
+description: Everyone's heard of them
+
+dn: ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Alumni Association
+ou: Alabama
+
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+st: alumni association
+st: alabama
+
+dn: ou=Information Technology Division,ou=People,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Information Technology Division
+ou: The IT Crowd
+description:: aMODwoPDgsKCw4PCgsOCwotFVlZQw4PCg8OCwoPDg8KCw4LCv0zDg8KDw4LCgsOD
+ woLDgsKKT8ODwoPDgsKDw4PCgsOCwqs6w4PCg8OCwoLDg8KCw4LCjUQkw4PCg8OCwoLDg8KCw4LCi
+ 01QUcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoLDg8KCw4LCik/Dg8KDw4
+ LCgsODwoLDgsKLRCQoZitEJMODwoPDgsKCw4PCgsOCwrfDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoP
+ Dg8KCw4LCgcODwoPDgsKDw4PCgsOCwqHDg8KDw4LCgsODwoLDgsKLRCQkZitEJMODwoPDgsKCw4PC
+ gsOCwrfDg8KDw4LCg8ODwoLDgsKQw4PCg8OCwoPDg8KCw4LCisODwoPDgsKCw4PCgsOCwotFUVZqU
+ MODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKAw4PCg8OCwoLDg8KCw4LCik85dCTDg8KDw4
+ LCgsODwoLDgsKFQ8ODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4L
+ Cvzl0JMODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoPD
+ gsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKLRCTDg8KDw4LCgsODwoLDgsKDw4PCg8OCwoLDg8KCw
+ 4LCuMODwoPDgsKDw4PCgsOCwoR0Q8ODwoPDgsKCw4PCgsOCwoM9w4PCg8OCwoPDg8KCw4LChMODwo
+ PDgsKDw4PCgsOCwoFOdTrDg8KDw4LCg8ODwoLDgsKHw4PCg8OCwoPDg8KCw4LChMODwoPDgsKDw4P
+ CgsOCwoFOw4PCg8OCwoPDg8KCw4LCqMODwoPDgsKDw4PCgsOCwrtHw4PCg8OCwoLDg8KCw4LChcOD
+ woPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsK4dMODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODw
+ oLDgsKtR8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCiMODwo
+ PDgsKDw4PCgsOCwr9SfGrDg8KDw4LCgsODwoLDgsKLQGgxw4PCg8OCwoPDg8KCw4LCoWhQw4PCg8O
+ CwoPDg8KCw4LCv8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKKT8ODwoPDgsKCw4PCgsOC
+ wotEJDDDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHTDg8KDw4LCgsODwoLDgsKDw4PCg
+ 8OCwoPDg8KCw4LCuHXDg8KDw4LCgsODwoLDgsKLRCRqw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4
+ PCgsOCwojDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpPDg8K
+ Dw4LCg8ODwoLDgsKQXV9eW8ODwoPDgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsKEw4PCg8OCwoPD
+ g8KCw4LCgsODwoPDgsKDw4PCgsOCwozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODw
+ oPDgsKDw4PCgsOCwozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgs
+ OCwoxWV8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKxw4PCg8OCwoLDg8KCw4LCi3wkw4P
+ Cg8OCwoLDg8KCw4LCjcODwoPDgsKCw4PCgsOCwofDg8KDw4LCg8ODwoLDgsKof8ODwoPDgsKDw4PC
+ gsOCwr/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoLDg8KCw4LCg8ODwoPDgsKDw4PCgsOCwrh5w4PCg
+ 8OCwoLDg8KCw4LChzQzw4PCg8OCwoPDg8KCw4LCicODwoPDgsKCw4PCgsOCworDg8KDw4LCgsODwo
+ LDgsKIw4PCg8OCwoLDg8KCw4LCuDFBw4PCg8OCwoPDg8KCw4LCvyTDg8KDw4LCgsODwoLDgsKNdDF
+ Bw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODwoPD
+ gsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoLDg8KCw
+ 4LCi8ODwoPDgsKDw4PCgsOCwo7Dg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw4LCv8ODwoPDgs
+ KCw4PCgsOCwoTDg8KDw4LCgsODwoLDgsKAdcODwoPDgsKDw4PCgsOCwqhtw4PCg8OCwoLDg8KCw4L
+ ChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKEw4PCg8OCwoPDg8KCw4LCsMODwoPDgsKC
+ w4PCgsOCwrhfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCt
+ sODwoPDgsKDw4PCgsOCwq7Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4
+ PCgsOCwoPDg8KDw4LCg8ODwoLDgsKoZsODwoPDgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsK4w4P
+ Cg8OCwoLDg8KCw4LCh8ODwoPDgsKDw4PCgsOCwpUzw4PCg8OCwoPDg8KCw4LCicODwoPDgsKCw4PC
+ gsOCworDg8KDw4LCgsODwoLDgsKISDJBw4PCg8OCwoPDg8KCw4LCvyTDg8KDw4LCgsODwoLDgsKNN
+ DJBw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKOw4PCg8OCwo
+ PDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpDDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8O
+ DwoPDgsKDw4PCgsOCwojDg8KDw4LCg8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCnEzDg8KDw4LCgsOD
+ woLDgsKLSEBmw4PCg8OCwoLDg8KCw4LCg3lwdSTDg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw
+ 4LCv8ODwoPDgsKCw4PCgsOCwobDg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODwoPDgs
+ KCw4PCgsOCwp/Dg8KDw4LCgsODwoLDgsKBw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwoj
+ Dg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODwoPDgsKCw4PCgsOCwpPDg8KDw4LCgsOD
+ woLDgsKBw4PCg8OCwoPDg8KCw4LCv1rDg8KDw4LCgsODwoLDgsKAw4PCg8OCwoLDg8KCw4LChMODw
+ oPDgsKCw4PCgsOCwodqw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwoBqaMODwoPDgsKCw4
+ PCgsOCwpBQw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKDIMODwoPDgsKCw4PCgsOCwopPw4PCg8OCwoL
+ Dg8KCw4LChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKOacODwoPDgsKCw4PCgsOCwrhf
+ XsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCw
+ oLDg8KCw4LCgcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKGw4PCg8OCwoLDg8KCw4LCgM
+ ODwoPDgsKCw4PCgsOCwoRJw4PCg8OCwoLDg8KCw4LCgcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsO
+ DwoLDgsKIw4PCg8OCwoLDg8KCw4LCgMODwoPDgsKCw4PCgsOCwoQ9w4PCg8OCwoLDg8KCw4LCgcOD
+ woPDgsKDw4PCgsOCwr9aw4PCg8OCwoLDg8KCw4LCgMODwoPDgsKCw4PCgsOCwoQxw4PCg8OCwoLDg
+ 8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwoM9w4PCg8OCwoPDg8KCw4LCm0
+ 7Dg8KDw4LCgsODwoLDgsKEw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsK
+ Cw4PCgsOCwrhfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLD
+ gsKCw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODw
+ oPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgs
+ OCwo7Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoLDg8KCw4LCkMODwoPDgsKDw4PCgsOCwojDg8KDw4L
+ CgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCiMODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODwoLDgsK+
+ S8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKww4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKDw
+ 4PCgsOCwoTDg8KDw4LCgsODwoLDgsKKT1DDg8KDw4LCg8ODwoLDgsKoRsODwoPDgsKCw4PCgsOCwo
+ vDg8KDw4LCg8ODwoLDgsK4w4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwrZ0Y8ODwoPDgsK
+ Cw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK/dF/Dg8KDw4LCgsODwoLDgsKhdHpPw4PCg8OCwoLDg8KC
+ w4LCi8ODwoPDgsKDw4PCgsOCwo5Qw4PCg8OCwoPDg8KCw4LCqC1Jw4PCg8OCwoLDg8KCw4LChcODw
+ oPDgsKDw4PCgsOCwoB1RMODwoPDgsKCw4PCgsOCwqFwek/Dg8KDw4LCgsODwoLDgsKLw4PCg8OCwo
+ PDg8KCw4LCj1DDg8KDw4LCg8ODwoLDgsKoScODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsK
+ AdTPDg8KDw4LCgsODwoLDgsKhbHpPw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo5Qw4PC
+ g8OCwoPDg8KCw4LCqEnDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHXDg8KDw4LCgsODw
+ oLDgsKhaHpPw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo9Qw4PCg8OCwoPDg8KCw4LCqM
+ ODwoPDgsKDw4PCgsOCwrpIw4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwoB1M8ODwoPDgsK
+ Dw4PCgsOCwoBfXsODwoPDgsKDw4PCgsOCwoLDg8KDw4LCgsODwoLDgsK4X17Dg8KDw4LCg8ODwoLD
+ gsKCw4PCg8OCwoLDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgjPDg8KDw4LCg8ODwoLDgsKAX17Dg
+ 8KDw4LCg8ODwoLDgsKCw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo7Dg8KDw4LCg8ODwo
+ LDgsKoJ8ODwoPDgsKDw4PCgsOCwq3Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODwoP
+ DgsKCw4PCgsOCwoPDg8KDw4LCg8ODwoLDgsK4aHU5w4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PC
+ gsOCwovDg8KDw4LCg8ODwoLDgsKOw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpDDg8KDw
+ 4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgs
+ KIw4PCg8OCwoPDg8KCw4LCv8ODwoPDgsKCw4PCgsOCwpLDg8KDw4LCg8ODwoLDgsKEw4PCg8OCwoL
+ Dg8KCw4LChcODwoPDgsKDw4PCgsOCwoB0IcODwoPDgsKCw4PCgsOCwovDg8KDw4LCgsODwoLDgsKA
+ w4PCg8OCwoPDg8KCw4LCtMODwoPDgsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsKAdGbDg8KDw4LCg
+ sODwoLDgsKLQGY9dGY9dTPDg8KDw4LCg8ODwoLDgsKAX17Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwo
+ LDg8KCw4LCuF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwrhfXsODwoPDgsKDw4PCgsO
+ CwoIzw4PCg8OCwoPDg8KCw4LCgF9ew4PCg8OCwoPDg8KCw4LCgsODwoPDgsKCw4PCgsOCwovDg8KD
+ w4LCg8ODwoLDgsK/Ri9BUC9BRi9BWi9BZC9BWzBBZC9BZTBBZC9BZC9BbzBBZC9BeTBBw4PCg8OCw
+ oLDg8KCw4LCgzBBMUFhMUFrMUE=
+description:: UF7Dg8KDw4LCg8ODwoLDgsKCw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOC
+ wozDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOCwozDg8KDw4LCg
+ 8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCqFDDg8KDw4LCg8ODwoLDgsKpRsODwoPDgsKDw4PCgsOCwo
+ zDg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKDw4PCgsOCwozDg8KDw4LCg8O
+ DwoLDgsKMw4PCg8OCwoPDg8KCw4LCjMODwoPDgsKCw4PCgsOCwotEJCDDg8KDw4LCgsODwoLDgsKD
+ w4PCg8OCwoPDg8KCw4LCrMODwoPDgsKCw4PCgsOCwotUJCRTw4PCg8OCwoLDg8KCw4LCi1wkJFbDg
+ 8KDw4LCgsODwoLDgsKJTCRXVVBSU8ODwoPDgsKDw4PCgsOCwqjDg8KDw4LCg8ODwoLDgsKdT8ODwo
+ PDgsKCw4PCgsOCwoN8JDB1w4PCg8OCwoPDg8KCw4LCh8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCg8O
+ DwoLDgsKBTsODwoPDgsKDw4PCgsOCwqktw4PCg8OCwoLDg8KCw4LCg3wkMHTDg8KDw4LCgsODwoLD
+ gsKDfCQww4PCg8OCwoLDg8KCw4LChTPDg8KDw4LCg8ODwoLDgsK2OTXDg8KDw4LCg8ODwoLDgsKAw
+ 4PCg8OCwoPDg8KCw4LCgU7Dg8KDw4LCgsODwoLDgsKEIMODwoPDgsKCw4PCgsOCwqFIw4PCg8OCwo
+ PDg8KCw4LChU7Dg8KDw4LCgsODwoLDgsKJNcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCg8ODwoLDgsK
+ BTsODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsKIw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKD
+ w4PCgsOCwr9TXMODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGw4PCg8OCwoLDg8KCw
+ 4LChMODwoPDgsKCw4PCgsOCwpHDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLIEjDg8
+ KDw4LCg8ODwoLDgsKFTlDDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv1Ngw4PCg8OCwoL
+ Dg8KCw4LCi8ODwoPDgsKDw4PCgsOCwpjDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCm3Rx
+ w4PCg8OCwoLDg8KCw4LCizvDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCi8ODwoPDgsKDw
+ 4PCgsOCwr9XaMODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGdGLDg8KDw4LCgsODwo
+ LDgsKLf2zDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCi1D
+ Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8OD
+ woLDgsKow4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwq10SmgoT03Dg8KDw4LCgsODwoLDg
+ sKLw4PCg8OCwoPDg8KCw4LCjcODwoPDgsKDw4PCgsOCwqggTMODwoPDgsKCw4PCgsOCwoXDg8KDw4
+ LCg8ODwoLDgsKAdDrDg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLTSBQUcODwoPDgsK
+ Dw4PCgsOCwr/Dg8KDw4LCg8ODwoLDgsKMw4PCg8OCwoLDg8KCw4LCik/Dg8KDw4LCgsODwoLDgsKL
+ RCQoZitEJCDDg8KDw4LCgsODwoLDgsK3w4PCg8OCwoPDg8KCw4LCiMODwoPDgsKDw4PCgsOCwoHDg
+ 8KDw4LCg8ODwoLDgsKhw4PCg8OCwoLDg8KCw4LCi0QkJGYrRCTDg8KDw4LCgsODwoLDgsK3w4PCg8
+ OCwoPDg8KCw4LCkMODwoPDgsKDw4PCgsOCworDg8KDw4LCgsODwoLDgsKLRSBRVmpQw4PCg8OCwoP
+ Dg8KCw4LCv8ODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsODwoLDgsKKTzl0JHXDg8KDw4LCgsODwoLD
+ gsKhOXQkw4PCg8OCwoLDg8KCw4LChW/Dg8KDw4LCg8ODwoLDgsK/w4PCg8OCwoPDg8KCw4LCv8ODw
+ oPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKhRMODwoPDgsKDw4PCgsOCwoVOw4PCg8OCwoLDg8
+ KCw4LCi8ODwoPDgsKDw4PCgsOCwojDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCv1Ncw4P
+ Cg8OCwoLDg8KCw4LCiUQkw4PCg8OCwoLDg8KCw4LChcODwoPDgsKDw4PCgsOCwoDDg8KDw4LCgsOD
+ woLDgsKEw4PCg8OCwoPDg8KCw4LCtjPDg8KDw4LCg8ODwoLDgsK2w4PCg8OCwoLDg8KCw4LCjUQkw
+ 4PCg8OCwoLDg8KCw4LCiyBEw4PCg8OCwoPDg8KCw4LChU5Qw4PCg8OCwoLDg8KCw4LCi8ODwoPDgs
+ KDw4PCgsOCwr9TYMODwoPDgsKCw4PCgsOCwovDg8KDw4LCg8ODwoLDgsK4w4PCg8OCwoLDg8KCw4L
+ ChcODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKEw4PCg8OCwoPDg8KCw4LCkMODwoPDgsKC
+ w4PCgsOCwovDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCj8ODwoPDgsKDw4PCgsOCwr9Ta
+ MODwoPDgsKCw4PCgsOCwolEJDvDg8KDw4LCg8ODwoLDgsKGw4PCg8OCwoLDg8KCw4LChMODwoPDgs
+ KCw4PCgsOCwr3Dg8KDw4LCgsODwoLDgsKNRCTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4L
+ Cj1DDg8KDw4LCg8ODwoLDgsK/U2zDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoPDg8KCw4LCqMODwoPD
+ gsKCw4PCgsOCwoXDg8KDw4LCg8ODwoLDgsKtw4PCg8OCwoLDg8KCw4LChMODwoPDgsKCw4PCgsOCw
+ p9oMMODwoPDgsKDw4PCgsOCwolMw4PCg8OCwoLDg8KCw4LCi8ODwoPDgsKDw4PCgsOCwo3Dg8KDw4
+ LCg8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCq0vDg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4L
+ CgMODwoPDgsKCw4PCgsOCwoTDg8KDw4LCgsODwoLDgsKLw4PCg8OCwoLDg8KCw4LCi0QkOcODwoPD
+ gsKCw4PCgsOCwrDDg8KDw4LCg8ODwoLDgsKEdEU5w4PCg8OCwoLDg8KCw4LCtTR0PcODwoPDgsKCw
+ 4PCgsOCwovDg8KDw4LCg8ODwoLDgsKNw4PCg8OCwoPDg8KCw4LCqMODwoPDgsKDw4PCgsOCwo5Lw4
+ PCg8OCwoLDg8KCw4LCi0AgUMODwoPDgsKDw4PCgsOCwr/Dg8KDw4LCgsODwoLDgsKsw4PCg8OCwoL
+ Dg8KCw4LCik/Dg8KDw4LCgsODwoLDgsKFw4PCg8OCwoPDg8KCw4LCgHUow4PCg8OCwoLDg8KCw4LC
+ i8ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCgsODwoLDgsKJw4PCg8OCwoLDg8KCw4LCtTTDg8KDw4LCg
+ 8ODwoLDgsKow4PCg8OCwoPDg8KCw4LCl8ODwoPDgsKDw4PCgsOCwrtWw4PCg8OCwoLDg8KCw4LCi8
+ ODwoPDgsKDw4PCgsOCwo3Dg8KDw4LCg8ODwoLDgsKow4PCg8OCwoLDg8KCw4LCnw==
+
+
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+objectClass: OpenLDAPperson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+uid: bjorn
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+userPassword:: Ympvcm4=
+homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+description: Hiker, biker
+postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
+mail: bjorn@mailgw.example.com
+homePhone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimileTelephoneNumber: +1 313 555 2177
+telephoneNumber: +1 313 555 0355
+title: Hiker, biker
+ou: Information Technology Division
+ou: The IT Crowd
+
diff --git a/contrib/slapd-modules/variant/tests/data/test005-variant-missing.ldif b/contrib/slapd-modules/variant/tests/data/test005-variant-missing.ldif
new file mode 100644
index 0000000..54fd3a5
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test005-variant-missing.ldif
@@ -0,0 +1,4 @@
+dn: ou=People,dc=example,dc=com
+changetype: modify
+replace: seealso
+seealso: dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/data/test006-config.ldif b/contrib/slapd-modules/variant/tests/data/test006-config.ldif
new file mode 100644
index 0000000..c668134
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test006-config.ldif
@@ -0,0 +1,61 @@
+dn: name={4}Mark,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=description,name={4}Mark,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: cn
+olcVariantAlternativeEntry: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+
+dn: name={5}Elliot,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: sn=Elliot,ou=Add & Delete,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=title,name={5}Elliot,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: cn
+olcVariantAlternativeEntry: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=description,name={5}Elliot,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: cn=Added by Bjorn,ou=Add & Delete,dc=example,dc=com
+
+dn: name={6}Doe,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: sn=Doe,ou=Add & Delete,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=title,name={6}Doe,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: cn
+olcVariantAlternativeEntry: cn=John Doe,ou=Information Technology Division,ou=People,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=description,name={6}Doe,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: cn=Added by Bjorn,ou=Add & Delete,dc=example,dc=com
+
+dn: name={7}Group,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantVariant
+olcVariantEntry: cn=Group,ou=Add & Delete,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=seeAlso,name={7}Group,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: member
+olcVariantAlternativeEntry: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
+
+dn: olcVariantVariantAttribute=description,name={7}Group,olcOverlay={0}variant,olcDatabase={1}@BACKEND@,cn=config
+changetype: add
+objectclass: olcVariantAttribute
+olcVariantAlternativeAttribute: description
+olcVariantAlternativeEntry: cn=Alumni Assoc Staff,ou=Groups,dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/data/test006-out.ldif b/contrib/slapd-modules/variant/tests/data/test006-out.ldif
new file mode 100644
index 0000000..03910c0
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test006-out.ldif
@@ -0,0 +1,151 @@
+# reading Mark Elliot as anonymous
+
+# reading the same as various users
+dn: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: Mark A Elliot
+sn: Elliot
+uid: melliot
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 199 Outer Drive $ Ypsilanti, MI 48198
+homePhone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.example.com
+pager: +1 313 555 7671
+facsimileTelephoneNumber: +1 313 555 7762
+telephoneNumber: +1 313 555 4177
+description: Mark A Elliot
+
+dn: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: Mark Elliot
+sn: Elliot
+uid: melliot
+postalAddress: Alumni Association $ 111 Maple St $ Anytown, MI 48109
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+homePostalAddress: 199 Outer Drive $ Ypsilanti, MI 48198
+homePhone: +1 313 555 0388
+drink: Gasoline
+title: Director, UM Alumni Association
+mail: melliot@mail.alumni.example.com
+pager: +1 313 555 7671
+facsimileTelephoneNumber: +1 313 555 7762
+telephoneNumber: +1 313 555 4177
+description: Mark Elliot
+
+
+# Add & Delete subtree contents as seen by Babs
+dn: ou=Add & Delete,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Add & Delete
+
+dn: sn=Doe,ou=Add & Delete,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: John
+uid: jd
+sn: Doe
+title: John Doe
+
+dn: sn=Elliot,ou=Add & Delete,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: Mark
+uid: me
+sn: Elliot
+title: Mark A Elliot
+
+dn: cn=group,ou=Add & Delete,dc=example,dc=com
+objectClass: groupOfNames
+member: dc=example,dc=com
+cn: group
+description: All Alumni Assoc Staff
+seeAlso: cn=Manager,dc=example,dc=com
+seeAlso: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+
+
+# Add & Delete subtree contents as seen by Bjorn
+dn: ou=Add & Delete,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Add & Delete
+
+dn: sn=Doe,ou=Add & Delete,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: John
+uid: jd
+sn: Doe
+title: Jonathon Doe
+
+dn: sn=Elliot,ou=Add & Delete,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: Mark
+uid: me
+sn: Elliot
+title: Mark Elliot
+
+dn: cn=group,ou=Add & Delete,dc=example,dc=com
+objectClass: groupOfNames
+member: dc=example,dc=com
+cn: group
+description: All Alumni Assoc Staff
+seeAlso: cn=Manager,dc=example,dc=com
+seeAlso: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+
+
+# Final state of ou=Add & Delete,dc=example,dc=com as seen by the Manager
+dn: ou=Add & Delete,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Add & Delete
+
+dn: cn=Added by Bjorn,ou=Add & Delete,dc=example,dc=com
+objectClass: inetOrgPerson
+sn: Jensen
+cn: Added by Bjorn
+description: added by jaj (should succeed)
+
+dn: sn=Doe,ou=Add & Delete,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: John
+uid: jd
+sn: Doe
+description: added by jaj (should succeed)
+title: John Doe
+title: Jonathon Doe
+
+dn: sn=Elliot,ou=Add & Delete,dc=example,dc=com
+objectClass: OpenLDAPperson
+cn: Mark
+uid: me
+sn: Elliot
+description: added by jaj (should succeed)
+title: Mark Elliot
+title: Mark A Elliot
+
+dn: cn=group,ou=Add & Delete,dc=example,dc=com
+objectClass: groupOfNames
+member: dc=example,dc=com
+cn: group
+description: All Alumni Assoc Staff
+description: another one added by bjorn (should succeed)
+seeAlso: cn=Manager,dc=example,dc=com
+seeAlso: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Jane Doe,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Jennifer Smith,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Mark Elliot,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
+seeAlso: cn=Bjorn Jensen,ou=Information Technology DivisioN,ou=People,dc=examp
+ le,dc=com
+seeAlso: cn=Barbara Jensen,ou=Information Technology DivisioN,ou=People,dc=exa
+ mple,dc=com
+
diff --git a/contrib/slapd-modules/variant/tests/data/test007-out.ldif b/contrib/slapd-modules/variant/tests/data/test007-out.ldif
new file mode 100644
index 0000000..cf1aac8
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test007-out.ldif
@@ -0,0 +1,6 @@
+# Testing searches against attribute supertypes...
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+st: Alumni Association
+
diff --git a/contrib/slapd-modules/variant/tests/data/test010-out.ldif b/contrib/slapd-modules/variant/tests/data/test010-out.ldif
new file mode 100644
index 0000000..28603e1
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test010-out.ldif
@@ -0,0 +1,52 @@
+# Test 1, trigger sizelimit without overlay interference
+dn: cn=Bjorn Jensen,ou=Information Technology Division,ou=People,dc=example,dc
+ =com
+objectClass: OpenLDAPperson
+cn: Bjorn Jensen
+cn: Biiff Jensen
+sn: Jensen
+uid: bjorn
+seeAlso: cn=All Staff,ou=Groups,dc=example,dc=com
+userPassword:: Ympvcm4=
+homePostalAddress: 19923 Seven Mile Rd. $ South Lyon, MI 49999
+drink: Iced Tea
+description: Hiker, biker
+title: Director, Embedded Systems
+postalAddress: Info Tech Division $ 535 W. William St. $ Anytown, MI 48103
+mail: bjorn@mailgw.example.com
+homePhone: +1 313 555 5444
+pager: +1 313 555 4474
+facsimileTelephoneNumber: +1 313 555 2177
+telephoneNumber: +1 313 555 0355
+Size limit exceeded (4)
+
+# Test 2, check sizelimit is not triggered when it matches the number of entries returned
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+st: Alumni Association
+
+dn: ou=People,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: extensibleObject
+ou: People
+uidNumber: 0
+gidNumber: 0
+description: The Example, Inc. at Anytown
+
+dn: cn=Manager,dc=example,dc=com
+objectClass: person
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userPassword:: c2VjcmV0
+
+# Test 3, check sizelimit will stop at the right time
+dn: ou=Groups,dc=example,dc=com
+objectClass: organizationalUnit
+ou: Groups
+st: Alumni Association
+Size limit exceeded (4)
+
diff --git a/contrib/slapd-modules/variant/tests/data/test011-out.ldif b/contrib/slapd-modules/variant/tests/data/test011-out.ldif
new file mode 100644
index 0000000..07604f8
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test011-out.ldif
@@ -0,0 +1,10 @@
+# ldapsearch does not return anything tangible in the output if it enounters a referral
+
+# Asking for the referral will return LDAP_REFERRAL
+Referral (10)
+Matched DN: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
+Referral: ldap://hostB/cn=Gern%20Jensen,ou=Information%20Technology%20Division,ou=People,dc=example,dc=com??sub
+# Asking for anything under a referral will do the same
+Referral (10)
+Matched DN: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
+Referral: ldap://hostB/cn=child,cn=Gern%20Jensen,ou=Information%20Technology%20Division,ou=People,dc=example,dc=com??sub
diff --git a/contrib/slapd-modules/variant/tests/data/test012-data.ldif b/contrib/slapd-modules/variant/tests/data/test012-data.ldif
new file mode 100644
index 0000000..8b8d8b3
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test012-data.ldif
@@ -0,0 +1,13 @@
+dn: dc=demonstration,dc=com
+changetype: add
+objectclass: organization
+objectclass: domainRelatedObject
+objectclass: dcobject
+o: demo
+associateddomain: demonstration.com
+
+dn: ou=Societies,dc=demonstration,dc=com
+changetype: add
+objectclass: organizationalUnit
+ou: Societies
+seealso: dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/data/test012-out.ldif b/contrib/slapd-modules/variant/tests/data/test012-out.ldif
new file mode 100644
index 0000000..bd31fa0
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/test012-out.ldif
@@ -0,0 +1,9 @@
+dn: ou=People,dc=example,dc=com
+objectClass: organizationalUnit
+objectClass: extensibleObject
+ou: People
+uidNumber: 0
+gidNumber: 0
+seealso: dc=example,dc=com
+description: The Example, Inc. at Anytown
+
diff --git a/contrib/slapd-modules/variant/tests/data/variant.conf b/contrib/slapd-modules/variant/tests/data/variant.conf
new file mode 100644
index 0000000..dba6c46
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/data/variant.conf
@@ -0,0 +1,17 @@
+overlay variant
+passReplication TRUE
+
+variantDN ou=People,dc=example,dc=com
+variantSpec seealso seealso ou=Societies,dc=example,dc=com
+variantSpec description description dc=example,dc=com
+
+variantRegex "(.*),(ou=.*technology.*)(,)dc=example,dc=com"
+variantRegexSpec title description $0
+variantRegexSpec ou ou "$2$3dc=example$3dc=com"
+
+variantDN ou=Groups,dc=example,dc=com
+variantSpec st ou "ou=Alumni Association,ou=People,dc=example,dc=com"
+variantSpec description description ou=People,dc=example,dc=com
+
+variantRegex .*
+variantRegexSpec l l dc=example,dc=com
diff --git a/contrib/slapd-modules/variant/tests/run b/contrib/slapd-modules/variant/tests/run
new file mode 100755
index 0000000..6a38431
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/run
@@ -0,0 +1,229 @@
+#!/bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+USAGE="$0 [-b <backend>] [-c] [-k] [-l #] [-p] [-s {ro|rp}] [-u] [-w] <script>"
+
+TOPSRCDIR="${SRCDIR-$LDAP_SRC}"
+SRCDIR="${TOPSRCDIR}/tests"
+eval `grep EGREP_CMD= ${LDAP_BUILD}/tests/run`
+eval `$EGREP_CMD -e '^LN_S=' ${LDAP_BUILD}/tests/run`
+
+export SRCDIR TOPSRCDIR LN_S EGREP_CMD
+
+. "${SRCDIR}/scripts/defines.sh"
+
+BACKEND=
+CLEAN=no
+WAIT=0
+KILLSERVERS=yes
+PRESERVE=${PRESERVE-no}
+SYNCMODE=${SYNCMODE-rp}
+USERDATA=no
+LOOP=1
+COUNTER=1
+
+while test $# -gt 0 ; do
+ case "$1" in
+ -b | -backend)
+ BACKEND="$2"
+ shift; shift ;;
+
+ -c | -clean)
+ CLEAN=yes
+ shift ;;
+
+ -k | -kill)
+ KILLSERVERS=no
+ shift ;;
+ -l | -loop)
+ NUM="`echo $2 | sed 's/[0-9]//g'`"
+ if [ -z "$NUM" ]; then
+ LOOP=$2
+ else
+ echo "Loop variable not an int: $2"
+ echo "$USAGE"; exit 1
+ fi
+ shift ;
+ shift ;;
+
+ -p | -preserve)
+ PRESERVE=yes
+ shift ;;
+
+ -s | -syncmode)
+ case "$2" in
+ ro | rp)
+ SYNCMODE="$2"
+ ;;
+ *)
+ echo "unknown sync mode $2"
+ echo "$USAGE"; exit 1
+ ;;
+ esac
+ shift; shift ;;
+
+ -u | -userdata)
+ USERDATA=yes
+ shift ;;
+
+ -w | -wait)
+ WAIT=1
+ shift ;;
+
+ -)
+ shift
+ break ;;
+
+ -*)
+ echo "$USAGE"; exit 1
+ ;;
+
+ *)
+ break ;;
+ esac
+done
+
+eval `$EGREP_CMD -e '^AC' ${LDAP_BUILD}/tests/run`
+export `$EGREP_CMD -e '^AC' ${LDAP_BUILD}/tests/run | sed 's/=.*//'`
+
+if test -z "$BACKEND" ; then
+ for b in mdb ; do
+ if eval "test \"\$AC_$b\" != no" ; then
+ BACKEND=$b
+ break
+ fi
+ done
+ if test -z "$BACKEND" ; then
+ echo "No suitable default database backend configured" >&2
+ exit 1
+ fi
+fi
+
+BACKENDTYPE=`eval 'echo $AC_'$BACKEND`
+if test "x$BACKENDTYPE" = "x" ; then
+ BACKENDTYPE="unknown"
+fi
+
+# Backend features. indexdb: indexing and unchecked limit.
+# maindb: main storage backend. Currently index,limits,mode,paged results.
+INDEXDB=noindexdb MAINDB=nomaindb
+case $BACKEND in
+ mdb) INDEXDB=indexdb MAINDB=maindb ;;
+ ndb) INDEXDB=indexdb ;;
+esac
+
+export BACKEND BACKENDTYPE INDEXDB MAINDB \
+ WAIT KILLSERVERS PRESERVE SYNCMODE USERDATA \
+ SRCDIR
+
+if test $# = 0 ; then
+ echo "$USAGE"; exit 1
+fi
+
+# need defines.sh for the definitions of the directories
+. $SRCDIR/scripts/defines.sh
+
+SCRIPTDIR="${TOPDIR}/tests/scripts"
+
+export SCRIPTDIR
+
+SCRIPTNAME="$1"
+shift
+
+if test -x "${SCRIPTDIR}/${SCRIPTNAME}" ; then
+ SCRIPT="${SCRIPTDIR}/${SCRIPTNAME}"
+elif test -x "`echo ${SCRIPTDIR}/test*-${SCRIPTNAME}`"; then
+ SCRIPT="`echo ${SCRIPTDIR}/test*-${SCRIPTNAME}`"
+elif test -x "`echo ${SCRIPTDIR}/${SCRIPTNAME}-*`"; then
+ SCRIPT="`echo ${SCRIPTDIR}/${SCRIPTNAME}-*`"
+else
+ echo "run: ${SCRIPTNAME} not found (or not executable)"
+ exit 1;
+fi
+
+if test ! -r ${DATADIR}/test.ldif ; then
+ ${LN_S} ${SRCDIR}/data ${DATADIR}
+fi
+if test ! -r ${SCHEMADIR}/core.schema ; then
+ ${LN_S} ${TOPSRCDIR}/servers/slapd/schema ${SCHEMADIR}
+fi
+if test ! -r ./data; then
+ ${LN_S} ${TOPDIR}/tests/data ./
+fi
+
+if test -d ${TESTDIR} ; then
+ if test $PRESERVE = no ; then
+ echo "Cleaning up test run directory leftover from previous run."
+ /bin/rm -rf ${TESTDIR}
+ elif test $PRESERVE = yes ; then
+ echo "Cleaning up only database directories leftover from previous run."
+ /bin/rm -rf ${TESTDIR}/db.*
+ fi
+fi
+if test $BACKEND = ndb ; then
+ mysql --user root <<EOF
+ drop database if exists db_1;
+ drop database if exists db_2;
+ drop database if exists db_3;
+ drop database if exists db_4;
+ drop database if exists db_5;
+ drop database if exists db_6;
+EOF
+fi
+mkdir -p ${TESTDIR}
+
+if test $USERDATA = yes ; then
+ if test ! -d userdata ; then
+ echo "User data directory (userdata) does not exist."
+ exit 1
+ fi
+ cp -R userdata/* ${TESTDIR}
+fi
+
+# disable LDAP initialization
+LDAPNOINIT=true; export LDAPNOINIT
+
+echo "Running ${SCRIPT} for ${BACKEND}..."
+while [ $COUNTER -le $LOOP ]; do
+ if [ $LOOP -gt 1 ]; then
+ echo "Running $COUNTER of $LOOP iterations"
+ fi
+ $SCRIPT $*
+ RC=$?
+
+ if test $CLEAN = yes ; then
+ echo "Cleaning up test run directory from this run."
+ /bin/rm -rf ${TESTDIR}
+ echo "Cleaning up symlinks."
+ /bin/rm -f ${DATADIR} ${SCHEMADIR}
+ fi
+
+ if [ $RC -ne 0 ]; then
+ if [ $LOOP -gt 1 ]; then
+ echo "Failed after $COUNTER of $LOOP iterations"
+ fi
+ exit $RC
+ else
+ COUNTER=`expr $COUNTER + 1`
+ if [ $COUNTER -le $LOOP ]; then
+ echo "Cleaning up test run directory from this run."
+ /bin/rm -rf ${TESTDIR}
+ fi
+ fi
+done
+exit $RC
diff --git a/contrib/slapd-modules/variant/tests/scripts/all b/contrib/slapd-modules/variant/tests/scripts/all
new file mode 100755
index 0000000..d6d6dc7
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/all
@@ -0,0 +1,102 @@
+#! /bin/sh
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+
+. $SRCDIR/scripts/defines.sh
+
+TB="" TN=""
+if test -t 1 ; then
+ TB=`$SHTOOL echo -e "%B" 2>/dev/null`
+ TN=`$SHTOOL echo -e "%b" 2>/dev/null`
+fi
+
+FAILCOUNT=0
+SKIPCOUNT=0
+SLEEPTIME=10
+
+echo ">>>>> Executing all LDAP tests for $BACKEND"
+
+if [ -n "$NOEXIT" ]; then
+ echo "Result Test" > $TESTWD/results
+fi
+
+for CMD in ${SCRIPTDIR}/test*; do
+ case "$CMD" in
+ *~) continue;;
+ *.bak) continue;;
+ *.orig) continue;;
+ *.sav) continue;;
+ *) test -f "$CMD" || continue;;
+ esac
+
+ # remove cruft from prior test
+ if test $PRESERVE = yes ; then
+ /bin/rm -rf $TESTDIR/db.*
+ else
+ /bin/rm -rf $TESTDIR
+ fi
+ if test $BACKEND = ndb ; then
+ mysql --user root <<EOF
+ drop database if exists db_1;
+ drop database if exists db_2;
+ drop database if exists db_3;
+ drop database if exists db_4;
+ drop database if exists db_5;
+ drop database if exists db_6;
+EOF
+ fi
+
+ BCMD=`basename $CMD`
+ if [ -x "$CMD" ]; then
+ echo ">>>>> Starting ${TB}$BCMD${TN} for $BACKEND..."
+ $CMD
+ RC=$?
+ if test $RC -eq 0 ; then
+ echo ">>>>> $BCMD completed ${TB}OK${TN} for $BACKEND."
+ else
+ echo ">>>>> $BCMD ${TB}failed${TN} for $BACKEND"
+ FAILCOUNT=`expr $FAILCOUNT + 1`
+
+ if [ -n "$NOEXIT" ]; then
+ echo "Continuing."
+ else
+ echo "(exit $RC)"
+ exit $RC
+ fi
+ fi
+ else
+ echo ">>>>> Skipping ${TB}$BCMD${TN} for $BACKEND."
+ SKIPCOUNT=`expr $SKIPCOUNT + 1`
+ RC="-"
+ fi
+
+ if [ -n "$NOEXIT" ]; then
+ echo "$RC $BCMD" >> $TESTWD/results
+ fi
+
+# echo ">>>>> waiting $SLEEPTIME seconds for things to exit"
+# sleep $SLEEPTIME
+ echo ""
+done
+
+if [ -n "$NOEXIT" ]; then
+ if [ "$FAILCOUNT" -gt 0 ]; then
+ cat $TESTWD/results
+ echo "$FAILCOUNT tests for $BACKEND ${TB}failed${TN}. Please review the test log."
+ else
+ echo "All executed tests for $BACKEND ${TB}succeeded${TN}."
+ fi
+fi
+
+echo "$SKIPCOUNT tests for $BACKEND were ${TB}skipped${TN}."
diff --git a/contrib/slapd-modules/variant/tests/scripts/common.sh b/contrib/slapd-modules/variant/tests/scripts/common.sh
new file mode 100755
index 0000000..3b155ad
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/common.sh
@@ -0,0 +1,115 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016-2017 by Ondřej Kuzník for Symas Corp.
+
+OVERLAY_CONFIG=${OVERLAY_CONFIG-data/config.ldif}
+
+mkdir -p $TESTDIR $DBDIR1
+
+echo "Running slapadd to build slapd database..."
+. $CONFFILTER $BACKEND $MONITORDB < $CONF > $ADDCONF
+$SLAPADD -f $ADDCONF -l $LDIFORDERED
+RC=$?
+if test $RC != 0 ; then
+ echo "slapadd failed ($RC)!"
+ exit $RC
+fi
+
+mkdir $TESTDIR/confdir
+. $CONFFILTER $BACKEND $MONITORDB < $CONF > $CONF1
+
+$SLAPPASSWD -g -n >$CONFIGPWF
+echo "database config" >>$CONF1
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >>$CONF1
+
+echo "Starting slapd on TCP/IP port $PORT1 for configuration..."
+$SLAPD -f $CONF1 -F $TESTDIR/confdir -h $URI1 -d $LVL > $LOG1 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$PID"
+
+sleep $SLEEP0
+
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -H $URI1 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting ${SLEEP1} seconds for slapd to start..."
+ sleep ${SLEEP1}
+done
+
+echo "Making a modification that will be hidden by the test config..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/hidden.ldif >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPSEARCH -D cn=config -H $URI1 -y $CONFIGPWF \
+ -s base -b 'cn=module{0},cn=config' 1.1 >$TESTOUT 2>&1
+RC=$?
+case $RC in
+0)
+ $LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: cn=module{0},cn=config
+changetype: modify
+add: olcModuleLoad
+olcModuleLoad: `pwd`/../variant.la
+EOMOD
+ ;;
+32)
+ $LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: cn=module,cn=config
+changetype: add
+objectClass: olcModuleList
+olcModuleLoad: `pwd`/../variant.la
+EOMOD
+ ;;
+*)
+ echo "Failed testing for module load entry"
+ exit $RC;
+ ;;
+esac
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Loading test variant configuration..."
+. $CONFFILTER $BACKEND $MONITORDB < $OVERLAY_CONFIG | \
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
diff --git a/contrib/slapd-modules/variant/tests/scripts/test001-config b/contrib/slapd-modules/variant/tests/scripts/test001-config
new file mode 100755
index 0000000..7a5559f
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test001-config
@@ -0,0 +1,209 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Applying invalid changes to config (should fail)..."
+for CHANGE in data/test001-*.ldif; do
+ echo "... $CHANGE"
+ . $CONFFILTER $BACKEND $MONITORDB < $CHANGE | \
+ $LDAPMODIFY -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1
+ RC=$?
+ case $RC in
+ 0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ ;;
+ 80)
+ echo "ldapmodify failed ($RC)"
+ ;;
+ *)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+ esac
+done
+
+# We run this search after the changes above and before restart so we can also
+# check the reconfiguration attempts actually had no side effects
+echo "Saving search output before server restart..."
+echo "# search output from dynamically configured server..." >> $SERVER3OUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ >> $SERVER3OUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Stopping slapd on TCP/IP port $PORT1..."
+kill -HUP $KILLPIDS
+KILLPIDS=""
+sleep $SLEEP0
+echo "Starting slapd on TCP/IP port $PORT1..."
+$SLAPD -F $TESTDIR/confdir -h $URI1 -d $LVL >> $LOG1 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$PID"
+
+sleep $SLEEP0
+
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -H $URI1 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting ${SLEEP1} seconds for slapd to start..."
+ sleep ${SLEEP1}
+done
+
+echo "Testing slapd.conf support..."
+mkdir $TESTDIR/conftest $DBDIR2
+. $CONFFILTER $BACKEND $MONITORDB < $CONFTWO \
+ | sed -e '/^argsfile.*/a\
+moduleload ../variant.la' \
+ -e '/database.*monitor/i\
+include data/variant.conf' \
+ > $CONF2
+echo "database config" >>$CONF2
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >>$CONF2
+
+$SLAPADD -f $CONF2 -l $LDIFORDERED
+$SLAPD -Tt -f $CONF2 -F $TESTDIR/conftest -d $LVL >> $LOG2 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "slaptest failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Starting slapd on TCP/IP port $PORT2..."
+$SLAPD -F $TESTDIR/conftest -h $URI2 -d $LVL >> $LOG2 2>&1 &
+PID=$!
+if test $WAIT != 0 ; then
+ echo PID $PID
+ read foo
+fi
+KILLPIDS="$KILLPIDS $PID"
+
+sleep $SLEEP0
+
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$MONITOR" -H $URI2 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting ${SLEEP1} seconds for slapd to start..."
+ sleep ${SLEEP1}
+done
+
+echo "Gathering overlay configuration from both servers..."
+echo "# overlay configuration from dynamically configured server..." >> $SERVER1OUT
+$LDAPSEARCH -D cn=config -H $URI1 -y $CONFIGPWF \
+ -b "olcOverlay={0}variant,olcDatabase={1}$BACKEND,cn=config" \
+ >> $SERVER1OUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "# overlay configuration from server configured from slapd.conf..." >> $SERVER2OUT
+$LDAPSEARCH -D cn=config -H $URI2 -y $CONFIGPWF \
+ -b "olcOverlay={0}variant,olcDatabase={1}$BACKEND,cn=config" \
+ >> $SERVER2OUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+# We've already filtered out the ordering markers, now sort the entries
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s a < $SERVER2OUT > $SERVER2FLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s a < $SERVER1OUT > $SERVER1FLT
+echo "Comparing filter output..."
+$CMP $SERVER2FLT $SERVER1FLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+rm $SERVER1OUT $SERVER2OUT
+
+echo "Comparing search output on both servers..."
+echo "# search output from dynamically configured server..." >> $SERVER1OUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ >> $SERVER1OUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "# search output from server configured from slapd.conf..." >> $SERVER2OUT
+$LDAPSEARCH -b "$BASEDN" -H $URI2 \
+ >> $SERVER2OUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SERVER1OUT > $SERVER1FLT
+$LDIFFILTER -s e < $SERVER2OUT > $SERVER2FLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $SERVER3OUT > $SERVER3FLT
+echo "Comparing filter output..."
+$CMP $SERVER3FLT $SERVER1FLT > $CMPOUT && \
+$CMP $SERVER3FLT $SERVER2FLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test002-add-delete b/contrib/slapd-modules/variant/tests/scripts/test002-add-delete
new file mode 100755
index 0000000..bd316b2
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test002-add-delete
@@ -0,0 +1,113 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Adding entry..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test002-01-entry.ldif >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Configuring entry as variant..."
+. $CONFFILTER $BACKEND $MONITORDB < data/additional-config.ldif | \
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Removing entry..."
+$LDAPDELETE -D $MANAGERDN -H $URI1 -w $PASSWD \
+ "cn=Gern Jensen,ou=Information Technology Division,ou=People,$BASEDN" \
+ >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapdelete failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Adding entry again (should fail)..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test002-01-entry.ldif >> $TESTOUT 2>&1
+RC=$?
+case $RC in
+0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ ;;
+19)
+ echo "ldapmodify failed ($RC)"
+ ;;
+*)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+echo "Adding a regex entry (should fail)..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test002-02-regex.ldif >> $TESTOUT 2>&1
+RC=$?
+case $RC in
+0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ ;;
+19)
+ echo "ldapmodify failed ($RC)"
+ ;;
+*)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+echo "Adding entry with offending attributes removed..."
+grep -v '^description:' data/test002-01-entry.ldif | \
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test003-search b/contrib/slapd-modules/variant/tests/scripts/test003-search
new file mode 100755
index 0000000..2284ab7
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test003-search
@@ -0,0 +1,113 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Testing searches against regular entries..."
+echo "# Testing searches against regular entries..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ "(|(name=Elliot)(description=*hiker*))" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches listing variants..."
+echo >> $SEARCHOUT
+echo "# Testing searches listing variants..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s one -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s base -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >> $SEARCHOUT
+$LDAPSEARCH -s base -H $URI1 \
+ -b "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN" \
+ '(ou=Information Technology Division)' \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >> $SEARCHOUT
+$LDAPSEARCH -b "cn=ITD Staff,ou=Groups,$BASEDN" -s base -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches filtering on variants..."
+echo >> $SEARCHOUT
+echo "# Testing searches filtering on variants..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ "(st=Alumni Association)" st \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test003-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test004-compare b/contrib/slapd-modules/variant/tests/scripts/test004-compare
new file mode 100755
index 0000000..c87d347
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test004-compare
@@ -0,0 +1,63 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Comparing a regular entry..."
+$LDAPCOMPARE -H $URI1 \
+ "cn=Mark Elliot,ou=Alumni Association,ou=People,$BASEDN" \
+ "cn:Mark Elliot" >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 6 && test $RC,$BACKEND != 5,null ; then
+ echo "ldapcompare failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+echo "Comparing a variant entry..."
+$LDAPCOMPARE -H $URI1 \
+ "ou=People,$BASEDN" \
+ "description:The Example, Inc. at Anytown" >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 6 && test $RC,$BACKEND != 5,null ; then
+ echo "ldapcompare failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+echo "Comparing a regex entry..."
+$LDAPCOMPARE -H $URI1 \
+ "cn=Barbara Jensen,ou=Information Technology Division,ou=People,$BASEDN" \
+ "ou:Information Technology Division" >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 6 && test $RC,$BACKEND != 5,null ; then
+ echo "ldapcompare failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test005-modify b/contrib/slapd-modules/variant/tests/scripts/test005-modify
new file mode 100755
index 0000000..4cbf289
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test005-modify
@@ -0,0 +1,120 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Modifying entry..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test005-changes.ldif >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+# for now, overlay returns success just after the modifications to the main
+# entry succeed, ignoring the rest should they fail
+echo "Modifying a nonexistent variant of an existing entry..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test005-variant-missing.ldif >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Configuring nonexistent entry as variant..."
+. $CONFFILTER $BACKEND $MONITORDB < data/additional-config.ldif | \
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Modifying an existing variant of above missing entry..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test005-modify-missing.ldif >> $TESTOUT 2>&1
+RC=$?
+case $RC in
+0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ ;;
+32)
+ echo "ldapmodify failed ($RC)"
+ ;;
+*)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+echo "Reading affected entries back..."
+echo "# Reading affected entries back..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ '(|(description=*heard*)(st=*)(ou=alabama)(ou=*IT*))' \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >>$SEARCHOUT
+$LDAPSEARCH -H $URI1 -s base \
+ -b "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test005-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test006-acl b/contrib/slapd-modules/variant/tests/scripts/test006-acl
new file mode 100755
index 0000000..6b34fb8
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test006-acl
@@ -0,0 +1,323 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+case "$BACKEND" in ldif | null)
+ echo "$BACKEND backend does not support access controls, test skipped"
+ exit 0
+esac
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+CONF=$ACLCONF
+. ${SCRIPTDIR}/common.sh
+
+echo "Applying test-specific configuration..."
+. $CONFFILTER $BACKEND $MONITORDB < data/test006-config.ldif | \
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: ou=Add & Delete,dc=example,dc=com
+changetype: add
+objectClass: organizationalUnit
+ou: Add & Delete
+
+dn: cn=group,ou=Add & Delete,dc=example,dc=com
+changetype: add
+objectclass: groupOfNames
+member: dc=example,dc=com
+
+dn: sn=Doe,ou=Add & Delete,dc=example,dc=com
+changetype: add
+objectclass: OpenLDAPperson
+cn: John
+uid: jd
+
+dn: sn=Elliot,ou=Add & Delete,dc=example,dc=com
+changetype: add
+objectclass: OpenLDAPperson
+cn: Mark
+uid: me
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing search ACL processing..."
+
+echo "# Try to read an entry inside the Alumni Association container.
+# It should give us noSuchObject if we're not bound..." \
+>> $SEARCHOUT
+# FIXME: temporarily remove the "No such object" message to make
+# the test succeed even if SLAP_ACL_HONOR_DISCLOSE is not #define'd
+$LDAPSEARCH -b "$MELLIOTDN" -H $URI1 "(objectclass=*)" \
+ 2>&1 | grep -v "No such object" >> $SEARCHOUT
+
+echo >>$SEARCHOUT
+echo "# ... and should return appropriate attributes if we're bound as anyone
+# under Example." \
+>> $SEARCHOUT
+$LDAPSEARCH -b "$MELLIOTDN" -H $URI1 \
+ -D "$BABSDN" -w bjensen "(objectclass=*)" >> $SEARCHOUT 2>&1
+
+$LDAPSEARCH -b "$MELLIOTDN" -H $URI1 \
+ -D "$BJORNSDN" -w bjorn "(objectclass=*)" >> $SEARCHOUT 2>&1
+
+echo >>$SEARCHOUT
+echo "# Add & Delete subtree contents as seen by Babs" >> $SEARCHOUT
+$LDAPSEARCH -b "ou=Add & Delete,dc=example,dc=com" -H $URI1 \
+ -D "$BABSDN" -w bjensen "(objectclass=*)" >> $SEARCHOUT 2>&1
+
+echo >>$SEARCHOUT
+echo "# Add & Delete subtree contents as seen by Bjorn" >> $SEARCHOUT
+$LDAPSEARCH -b "ou=Add & Delete,dc=example,dc=com" -H $URI1 \
+ -D "$BJORNSDN" -w bjorn "(objectclass=*)" >> $SEARCHOUT 2>&1
+
+echo "Testing modifications..."
+echo "... ACL on the alternative entry"
+$LDAPMODIFY -D "$BJORNSDN" -H $URI1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=group,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+add: seealso
+seealso: $BJORNSDN
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$BABSDN" -H $URI1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Alumni Assoc Staff, ou=Groups, dc=example, dc=com
+changetype: modify
+add: description
+description: added by bjensen (should fail)
+EOMODS
+RC=$?
+case $RC in
+50)
+ ;;
+0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+ ;;
+*)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=group,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+add: seealso
+seealso: $BABSDN
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$BJORNSDN" -H $URI1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Alumni Assoc Staff, ou=Groups, dc=example, dc=com
+changetype: modify
+add: description
+description: added by bjorn (removed later)
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$BABSDN" -H $URI1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Group,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+delete: description
+description: added by bjorn (removed later)
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$BJORNSDN" -H $URI1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Added by Bjorn,ou=Add & Delete,dc=example,dc=com
+changetype: add
+objectClass: inetOrgPerson
+sn: Jensen
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$BJORNSDN" -H $URI1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Group,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+add: description
+description: another one added by bjorn (should succeed)
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "... ACL on the variant entry"
+$LDAPMODIFY -D "$BABSDN" -H $URI1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Group,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+add: description
+description: added by bjensen (should fail)
+EOMODS
+RC=$?
+case $RC in
+50)
+ ;;
+0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+ ;;
+*)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+$LDAPMODIFY -D "$BJORNSDN" -H $URI1 -w bjorn >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: sn=Doe,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+add: description
+description: added by bjorn (will be removed)
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+$LDAPMODIFY -D "$BABSDN" -H $URI1 -w bjensen >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: cn=Added by Bjorn,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+replace: description
+description: added by bjensen (should fail)
+EOMODS
+RC=$?
+case $RC in
+50)
+ ;;
+0)
+ echo "ldapmodify should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit -1
+ ;;
+*)
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+$LDAPMODIFY -D "$JAJDN" -H $URI1 -w jaj >> \
+ $TESTOUT 2>&1 << EOMODS
+dn: sn=Elliot,ou=Add & Delete,dc=example,dc=com
+changetype: modify
+delete: description
+description: added by bjorn (will be removed)
+-
+add: description
+description: added by jaj (should succeed)
+EOMODS
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+sleep $SLEEP0
+
+echo >>$SEARCHOUT
+echo "Using ldapsearch to retrieve all the entries..."
+echo "# Using ldapsearch to retrieve all the entries..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "ou=Add & Delete,dc=example,dc=com" \
+ -D "$MANAGERDN" -H $URI1 -w $PASSWD \
+ 'objectClass=*' >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test006-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "comparison failed - operations did not complete correctly"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test007-subtypes b/contrib/slapd-modules/variant/tests/scripts/test007-subtypes
new file mode 100755
index 0000000..177fc33
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test007-subtypes
@@ -0,0 +1,67 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Comparing supertype of a variant attribute..."
+$LDAPCOMPARE -H $URI1 \
+ "ou=Groups,$BASEDN" \
+ "name:Alumni Association" >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 6 && test $RC,$BACKEND != 5,null ; then
+ echo "ldapcompare failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+echo "Testing searches against attribute supertypes..."
+echo "# Testing searches against attribute supertypes..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ "(&(name=groups)(name=Alumni Association))" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test007-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test008-variant-replication b/contrib/slapd-modules/variant/tests/scripts/test008-variant-replication
new file mode 100755
index 0000000..63e2d7e
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test008-variant-replication
@@ -0,0 +1,194 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+if test "$SYNCPROV" = syncprovno; then
+ echo "Syncrepl provider overlay not available, test skipped"
+ exit 0
+fi
+
+. ${SCRIPTDIR}/common.sh
+
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOMOD
+dn: olcOverlay={0}variant,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcVariantPassReplication
+olcVariantPassReplication: FALSE
+EOMOD
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+if test "$SYNCPROV" = syncprovmod; then
+ $LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOMOD
+dn: cn=module{0},cn=config
+changetype: modify
+add: olcModuleLoad
+olcModuleLoad: $LDAP_BUILD/servers/slapd/overlays/syncprov.la
+EOMOD
+
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+fi
+
+echo "Configuring syncprov on the provider..."
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOMOD
+dn: olcOverlay=syncprov,olcDatabase={1}$BACKEND,cn=config
+changetype: add
+objectclass: olcSyncProvConfig
+EOMOD
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+mkdir $DBDIR4
+
+echo "Starting consumer slapd on TCP/IP port $PORT4..."
+. $CONFFILTER $BACKEND $MONITORDB < $P1SRCONSUMERCONF > $CONF4
+$SLAPD -f $CONF4 -h $URI4 -d $LVL > $LOG4 2>&1 &
+CONSUMERPID=$!
+if test $WAIT != 0 ; then
+ echo CONSUMERPID $CONSUMERPID
+ read foo
+fi
+KILLPIDS="$KILLPIDS $CONSUMERPID"
+
+sleep $SLEEP0
+
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$BASEDN" -H $URI4 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting ${SLEEP1} seconds for consumer to start replication..."
+ sleep ${SLEEP1}
+done
+
+echo "Waiting ${SLEEP1} seconds for consumer to finish replicating..."
+sleep ${SLEEP1}
+
+echo "Testing searches against regular entries..."
+echo "# Testing searches against regular entries..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI4 \
+ "(|(name=Elliot)(description=*hiker*))" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches listing replicated variants..."
+echo >> $SEARCHOUT
+echo "# Testing searches listing replicated variants..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s one -H $URI4 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+# regex variants do not replicate correctly and this is documented
+echo >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s base -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+# regex variants do not replicate correctly and this is documented
+echo >> $SEARCHOUT
+$LDAPSEARCH -s base -H $URI1 \
+ -b "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN" \
+ '(ou=Information Technology Division)' \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+# regex variants do not replicate correctly and this is documented
+echo >> $SEARCHOUT
+$LDAPSEARCH -b "cn=ITD Staff,ou=Groups,$BASEDN" -s base -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches filtering on replicated variants..."
+echo >> $SEARCHOUT
+echo "# Testing searches filtering on replicated variants..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI4 \
+ "(st=Alumni Association)" st \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test003-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test009-ignored-replication b/contrib/slapd-modules/variant/tests/scripts/test009-ignored-replication
new file mode 100755
index 0000000..aefbfa9
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test009-ignored-replication
@@ -0,0 +1,227 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+if test "$SYNCPROV" = syncprovno; then
+ echo "Syncrepl provider overlay not available, test skipped"
+ exit 0
+fi
+
+. ${SCRIPTDIR}/common.sh
+
+if test "$SYNCPROV" = syncprovmod; then
+ $LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOMOD
+dn: cn=module{0},cn=config
+changetype: modify
+add: olcModuleLoad
+olcModuleLoad: $LDAP_BUILD/servers/slapd/overlays/syncprov.la
+EOMOD
+
+ RC=$?
+ if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ fi
+fi
+
+echo "Configuring syncprov on the provider..."
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ > $TESTOUT 2>&1 <<EOMOD
+dn: olcOverlay={0}syncprov,olcDatabase={1}$BACKEND,cn=config
+changetype: add
+objectclass: olcSyncProvConfig
+EOMOD
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+mkdir $DBDIR4 $TESTDIR/confdir-consumer
+
+echo "Starting consumer slapd on TCP/IP port $PORT4..."
+. $CONFFILTER $BACKEND $MONITORDB < $P1SRCONSUMERCONF > $CONF4
+
+echo "database config" >>$CONF4
+echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >>$CONF4
+
+$SLAPD -f $CONF4 -F $TESTDIR/confdir-consumer -h $URI4 -d $LVL > $LOG4 2>&1 &
+CONSUMERPID=$!
+if test $WAIT != 0 ; then
+ echo CONSUMERPID $CONSUMERPID
+ read foo
+fi
+KILLPIDS="$KILLPIDS $CONSUMERPID"
+
+sleep $SLEEP0
+
+echo "Setting up variant overlay on consumer..."
+$LDAPSEARCH -D cn=config -H $URI4 -y $CONFIGPWF \
+ -s base -b 'cn=module{0},cn=config' 1.1 >$TESTOUT 2>&1
+RC=$?
+case $RC in
+0)
+ $LDAPMODIFY -v -D cn=config -H $URI4 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: cn=module{0},cn=config
+changetype: modify
+add: olcModuleLoad
+olcModuleLoad: `pwd`/../variant.la
+EOMOD
+ ;;
+32)
+ $LDAPMODIFY -v -D cn=config -H $URI4 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: cn=module,cn=config
+changetype: add
+objectClass: olcModuleList
+olcModuleLoad: `pwd`/../variant.la
+EOMOD
+ ;;
+*)
+ echo "Failed testing for module load entry"
+ exit $RC;
+ ;;
+esac
+
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+. $CONFFILTER $BACKEND $MONITORDB < $OVERLAY_CONFIG | \
+$LDAPMODIFY -v -D cn=config -H $URI4 -y $CONFIGPWF \
+ > $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -s base -b "$BASEDN" -H $URI4 \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 0 ; then
+ break
+ fi
+ echo "Waiting ${SLEEP1} seconds for consumer to start replication..."
+ sleep ${SLEEP1}
+done
+
+echo "Waiting ${SLEEP1} seconds for consumer to finish replicating..."
+sleep ${SLEEP1}
+
+echo "Testing searches against regular entries..."
+echo "# Testing searches against regular entries..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI4 \
+ "(|(name=Elliot)(description=*hiker*))" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches listing replicated variants..."
+echo >> $SEARCHOUT
+echo "# Testing searches listing replicated variants..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s one -H $URI4 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s base -H $URI4 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >> $SEARCHOUT
+$LDAPSEARCH -s base -H $URI4 \
+ -b "cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN" \
+ '(ou=Information Technology Division)' \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo >> $SEARCHOUT
+$LDAPSEARCH -b "cn=ITD Staff,ou=Groups,$BASEDN" -s base -H $URI4 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches filtering on replicated variants..."
+echo >> $SEARCHOUT
+echo "# Testing searches filtering on replicated variants..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI4 \
+ "(st=Alumni Association)" st \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test003-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test010-limits b/contrib/slapd-modules/variant/tests/scripts/test010-limits
new file mode 100755
index 0000000..5828922
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test010-limits
@@ -0,0 +1,99 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Testing searches against regular entries..."
+echo "# Testing searches against regular entries..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ -z 1 "(|(name=Elliot)(description=*hiker*))" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+case $RC in
+0)
+ echo "ldapsearch should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ ;;
+4)
+ echo "sizelimit reached ($RC)"
+ ;;
+*)
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+echo "Testing searches listing variants where limits just fit..."
+echo "# Testing searches listing variants where limits just fit..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -s one -H $URI1 \
+ -z 3 >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Testing searches filtering on variants going over the specified limit..."
+echo "# Testing searches filtering on variants going over the specified limit..." >> $SEARCHOUT
+$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+ -z 1 "(name=Alumni Association)" \
+ >> $SEARCHOUT 2>&1
+RC=$?
+case $RC in
+0)
+ echo "ldapsearch should have failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+ ;;
+4)
+ echo "sizelimit reached ($RC)"
+ ;;
+*)
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+ ;;
+esac
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test010-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER -s e < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER -s e < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test011-referral b/contrib/slapd-modules/variant/tests/scripts/test011-referral
new file mode 100755
index 0000000..37d6d8c
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test011-referral
@@ -0,0 +1,169 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+TESTDN="cn=Gern Jensen,ou=Information Technology Division,ou=People,$BASEDN"
+
+echo "Adding referral..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: $TESTDN
+changetype: add
+objectclass: referral
+objectclass: extensibleObject
+ref: ldap://hostB HostB
+EOMOD
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Configuring referral as variant..."
+. $CONFFILTER $BACKEND $MONITORDB < data/additional-config.ldif | \
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Retrieving a referral variant..."
+echo "# Retrieving a referral variant..." >> $SEARCHOUT
+$LDAPSEARCH -LLL -b "$BASEDN" -H $URI1 \
+ '(cn=Gern Jensen)' >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch: unexpected result ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Retrieving a referral variant (returns a referral)..."
+echo "# Retrieving a referral variant (returns a referral)..." >> $SEARCHOUT
+$LDAPSEARCH -b "$TESTDN" -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 10 ; then
+ echo "ldapsearch: unexpected result ($RC)! (referral expected)"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Modifying a referral variant (returns a referral)..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: $TESTDN
+changetype: modify
+delete: description
+EOMOD
+RC=$?
+if test $RC != 10 ; then
+ echo "ldapmodify: unexpected result ($RC)! (referral expected)"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Comparing a referral variant (returns a referral)..."
+$LDAPCOMPARE -H $URI1 "$TESTDN" \
+ "description:The Example, Inc. at Anytown" >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 10; then
+ echo "ldapcompare: unexpected result ($RC)! (referral expected)"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+echo "Reconfiguring variant underneath a referral..."
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: name={4}test002,olcOverlay={0}variant,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcVariantEntry
+olcVariantEntry: cn=child,$TESTDN
+EOMOD
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Retrieving a variant under a referral (returns a referral)..."
+echo "# Retrieving a variant under a referral (returns a referral)..." >> $SEARCHOUT
+$LDAPSEARCH -b "cn=child,$TESTDN" -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 10 ; then
+ echo "ldapsearch: unexpected result ($RC)! (referral expected)"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Modifying a variant under a referral (returns a referral)..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ >> $TESTOUT 2>&1 <<EOMOD
+dn: cn=child,$TESTDN
+changetype: modify
+delete: description
+EOMOD
+RC=$?
+if test $RC != 10 ; then
+ echo "ldapmodify: unexpected result ($RC)! (referral expected)"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Comparing a variant under a referral (returns a referral)..."
+$LDAPCOMPARE -H $URI1 "cn=child,$TESTDN" \
+ "description:The Example, Inc. at Anytown" >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 10; then
+ echo "ldapcompare: unexpected result ($RC)! (referral expected)"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit 1
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test011-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0
diff --git a/contrib/slapd-modules/variant/tests/scripts/test012-crossdb b/contrib/slapd-modules/variant/tests/scripts/test012-crossdb
new file mode 100755
index 0000000..8854a1b
--- /dev/null
+++ b/contrib/slapd-modules/variant/tests/scripts/test012-crossdb
@@ -0,0 +1,90 @@
+#! /bin/sh
+## $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2016-2022 The OpenLDAP Foundation.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted only as authorized by the OpenLDAP
+## Public License.
+##
+## A copy of this license is available in the file LICENSE in the
+## top-level directory of the distribution or, alternatively, at
+## <http://www.OpenLDAP.org/license.html>.
+##
+## ACKNOWLEDGEMENTS:
+## This module was written in 2016 by Ondřej Kuzník for Symas Corp.
+
+echo "running defines.sh"
+. $SRCDIR/scripts/defines.sh
+
+. ${SCRIPTDIR}/common.sh
+
+echo "Setting up another database and variant using an alternate there..."
+mkdir $DBDIR2
+$LDAPMODIFY -v -D cn=config -H $URI1 -y $CONFIGPWF \
+ <<EOMOD >> $TESTOUT 2>&1
+dn: olcDatabase=ldif,cn=config
+changetype: add
+objectclass: olcLdifConfig
+olcSuffix: dc=demonstration,dc=com
+olcDbDirectory: $DBDIR2
+olcRootDn: $MANAGERDN
+
+dn: olcVariantVariantAttribute={1}seealso,name={0}variant,olcOverlay={0}variant,olcDatabase={1}$BACKEND,cn=config
+changetype: modify
+replace: olcVariantAlternativeEntry
+olcVariantAlternativeEntry: ou=Societies,dc=demonstration,dc=com
+EOMOD
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Adding alternate entry..."
+$LDAPMODIFY -D $MANAGERDN -H $URI1 -w $PASSWD \
+ -f data/test012-data.ldif >> $TESTOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapmodify failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+echo "Checking the variant gets resolved correctly..."
+echo "# Testing a search against a variant using another DB..." >> $SEARCHOUT
+#$LDAPSEARCH -b "$BASEDN" -H $URI1 \
+# "seealso=dc=example,dc=com" \
+$LDAPSEARCH -b "ou=People,$BASEDN" -s base -H $URI1 \
+ >> $SEARCHOUT 2>&1
+RC=$?
+if test $RC != 0 ; then
+ echo "ldapsearch failed ($RC)!"
+ test $KILLSERVERS != no && kill -HUP $KILLPIDS
+ exit $RC
+fi
+
+test $KILLSERVERS != no && kill -HUP $KILLPIDS
+
+LDIF=data/test012-out.ldif
+
+echo "Filtering ldapsearch results..."
+$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
+echo "Filtering expected entries..."
+$LDIFFILTER < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+test $KILLSERVERS != no && wait
+
+exit 0