summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@redhat.com>2010-11-22 16:54:05 -0500
committerNalin Dahyabhai <nalin@redhat.com>2010-11-22 16:54:05 -0500
commit35627435cea0c00e682b524ae3d0fa1d711ad4ab (patch)
tree90df463c953c5dbaee88a12e946bfedaf7e0f448
parent7624cdfed031262c4ea00d476ef591d352a2bc88 (diff)
downloadslapi-nis-35627435cea0c00e682b524ae3d0fa1d711ad4ab.tar.gz
slapi-nis-35627435cea0c00e682b524ae3d0fa1d711ad4ab.tar.xz
slapi-nis-35627435cea0c00e682b524ae3d0fa1d711ad4ab.zip
- handle a group with no explicitly-named container by treating the
entries as direct subordinates of the group entry
-rw-r--r--NEWS3
-rw-r--r--doc/sch-configuration.txt3
-rw-r--r--src/back-sch.c72
-rw-r--r--src/back-shr.c2
-rwxr-xr-xtests/test26-schema-single/after.sh13
-rw-r--r--tests/test26-schema-single/after.txt266
-rwxr-xr-xtests/test26-schema-single/before.sh13
-rw-r--r--tests/test26-schema-single/before.txt312
-rwxr-xr-xtests/test26-schema-single/change.sh2
-rw-r--r--tests/test26-schema-single/change.txt0
-rw-r--r--tests/test26-schema-single/description.txt1
-rw-r--r--tests/test26-schema-single/dse.ldif16
-rw-r--r--tests/test26-schema-single/userRoot.ldif48
13 files changed, 731 insertions, 20 deletions
diff --git a/NEWS b/NEWS
index 1536629..694a74e 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@
we'll attempt to participate in a search request.
* Add a deref_rf function which works like deref_r but also applies
filters at each step of the way.
+ * Do the more-or-less expected thing when a schema compat group
+ doesn't include a container RDN: assume the group DN is the only
+ container.
0.17 * Actually send portmap registrations to the right address.
0.16 * Fix NIS server startup problem when no listening port is explicitly
configured and we're using portmap instead of rpcbind (#500903).
diff --git a/doc/sch-configuration.txt b/doc/sch-configuration.txt
index 8fd04ed..93e5298 100644
--- a/doc/sch-configuration.txt
+++ b/doc/sch-configuration.txt
@@ -25,7 +25,8 @@ beneath the plugin's entry. These attributes are recognized:
appears. This level of grouping is primarily useful when using the
''referred'' function.
* schema-compat-container-rdn
- The RDN of this particular container.
+ The RDN of this particular container. If it's omitted, generated
+ entries will show up directly in the container group.
* schema-compat-search-base
One or more locations in the directory where candidate entries can be
found.
diff --git a/src/back-sch.c b/src/back-sch.c
index 6fc9c30..b22c44f 100644
--- a/src/back-sch.c
+++ b/src/back-sch.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008,2009 Red Hat, Inc.
+ * Copyright 2008,2009,2010 Red Hat, Inc.
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -51,7 +51,7 @@
#include "plugin.h"
#include "map.h"
-#define SCH_CONTAINER_CONFIGURATION_FILTER "(&(" SCH_CONTAINER_CONFIGURATION_GROUP_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_BASE_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_FILTER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_RDN_ATTR "=*))"
+#define SCH_CONTAINER_CONFIGURATION_FILTER "(&(" SCH_CONTAINER_CONFIGURATION_GROUP_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_BASE_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_FILTER_ATTR "=*)(" SCH_CONTAINER_CONFIGURATION_RDN_ATTR "=*))"
/* The data we ask the map cache to keep, for us, for each set. */
struct backend_set_data {
@@ -173,14 +173,20 @@ backend_set_config_read_config(struct plugin_state *state, Slapi_Entry *e,
/* Populate the returned structure. */
ret.common.state = state;
ret.common.group = slapi_dn_normalize(strdup(group));
- ret.common.set = slapi_dn_normalize(strdup(container));
+ ret.common.set = strlen(container) ?
+ slapi_dn_normalize(strdup(container)) :
+ strdup(container);
ret.common.bases = bases;
ret.common.entry_filter = entry_filter;
ret.common.ref_attrs = NULL;
ret.common.inref_attrs = NULL;
ret.common.ref_attr_list = NULL;
ret.common.inref_attr_list = NULL;
- dn = slapi_dn_plus_rdn(ret.common.group, ret.common.set);
+ if (strlen(ret.common.set) > 0) {
+ dn = slapi_dn_plus_rdn(ret.common.group, ret.common.set);
+ } else {
+ dn = strdup(ret.common.group);
+ }
ret.container_sdn = slapi_sdn_new_dn_passin(dn);
ret.rdn_format = rdn_format;
ret.attribute_format = attributes;
@@ -417,6 +423,7 @@ backend_set_config_entry_add_cb(Slapi_Entry *e, void *callback_data)
containers = backend_shr_get_vattr_strlist(state, e,
SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR);
for (i = 0; (groups != NULL) && (groups[i] != NULL); i++) {
+ /* If this is a multiple-container group, walk the list. */
for (j = 0;
(containers != NULL) && (containers[j] != NULL);
j++) {
@@ -424,6 +431,12 @@ backend_set_config_entry_add_cb(Slapi_Entry *e, void *callback_data)
groups[i],
containers[j]);
}
+ /* If there are no containers, add one with an empty name. */
+ if (containers == NULL) {
+ ret = backend_shr_set_config_entry_add(state, e,
+ groups[i],
+ "");
+ }
}
backend_shr_free_strlist(containers);
backend_shr_free_strlist(groups);
@@ -469,7 +482,7 @@ backend_get_set_config_entry_if_matching_cb(Slapi_Entry *e, void *callback_data)
cbdata = callback_data;
groups = backend_shr_get_vattr_strlist(cbdata->state, e, SCH_CONTAINER_CONFIGURATION_GROUP_ATTR);
sets = backend_shr_get_vattr_strlist(cbdata->state, e, SCH_CONTAINER_CONFIGURATION_CONTAINER_ATTR);
- if ((groups == NULL) || (sets == NULL)) {
+ if (groups == NULL) {
backend_shr_free_strlist(groups);
backend_shr_free_strlist(sets);
return TRUE;
@@ -490,6 +503,18 @@ backend_get_set_config_entry_if_matching_cb(Slapi_Entry *e, void *callback_data)
SCH_CONTAINER_CONFIGURATION_FILTER_ATTR);
}
}
+ if (sets == NULL) {
+ if (slapi_sdn_compare(cbdata->groupdn, cbdata->search_groupdn) == 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata->state->plugin_desc->spd_id,
+ "reading container configuration from \"%s\"\n",
+ slapi_entry_get_ndn(e));
+ cbdata->bases = backend_shr_get_vattr_strlist(cbdata->state, e,
+ SCH_CONTAINER_CONFIGURATION_BASE_ATTR);
+ cbdata->entry_filter = backend_shr_get_vattr_filter(cbdata->state, e,
+ SCH_CONTAINER_CONFIGURATION_FILTER_ATTR);
+ }
+ }
}
backend_shr_free_strlist(groups);
backend_shr_free_strlist(sets);
@@ -517,18 +542,25 @@ backend_get_set_config(struct plugin_state *state,
"\"%s\"/\"%s\"!\n", group, container);
return;
}
- setrdn = slapi_sdn_new_dn_byval(container);
- if (setrdn == NULL) {
- slapi_sdn_free(&groupdn);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "out of memory reading configuration for "
- "\"%s\"/\"%s\"!\n", group, container);
- return;
+ if (strlen(container) > 0) {
+ setrdn = slapi_sdn_new_dn_byval(container);
+ if (setrdn == NULL) {
+ slapi_sdn_free(&groupdn);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "out of memory reading configuration "
+ "for \"%s\"/\"%s\"!\n",
+ group, container);
+ return;
+ }
+ } else {
+ setrdn = NULL;
}
cbdata.groupdn = slapi_sdn_new();
if (cbdata.groupdn == NULL) {
- slapi_sdn_free(&setrdn);
+ if (setrdn != NULL) {
+ slapi_sdn_free(&setrdn);
+ }
slapi_sdn_free(&groupdn);
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
@@ -539,7 +571,9 @@ backend_get_set_config(struct plugin_state *state,
cbdata.setrdn = slapi_sdn_new();
if (cbdata.setrdn == NULL) {
slapi_sdn_free(&cbdata.groupdn);
- slapi_sdn_free(&setrdn);
+ if (setrdn != NULL) {
+ slapi_sdn_free(&setrdn);
+ }
slapi_sdn_free(&groupdn);
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
@@ -580,7 +614,9 @@ backend_get_set_config(struct plugin_state *state,
/* Clean up. */
slapi_sdn_free(&cbdata.setrdn);
slapi_sdn_free(&cbdata.groupdn);
- slapi_sdn_free(&setrdn);
+ if (setrdn != NULL) {
+ slapi_sdn_free(&setrdn);
+ }
slapi_sdn_free(&groupdn);
slapi_pblock_destroy(pb);
}
@@ -1161,8 +1197,8 @@ backend_check_empty(struct plugin_state *state,
&first_id,
&first_key_index)) {
slapi_log_error(SLAPI_LOG_FATAL, state->plugin_desc->spd_id,
- "warning: no entries set up under %s,%s\n",
- set, group);
+ "warning: no entries set up under %s%s%s\n",
+ set, set ? ", " : "",group);
}
}
diff --git a/src/back-shr.c b/src/back-shr.c
index 25bb14c..ef58d68 100644
--- a/src/back-shr.c
+++ b/src/back-shr.c
@@ -358,7 +358,7 @@ backend_shr_set_config_entry_add(struct plugin_state *state, Slapi_Entry *e,
}
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
- "initializing %s in %s, flag=%s (2)\n",
+ "initializing \"%s\" in %s, flag=%s (2)\n",
set_data->set, set_data->group, flag ? "yes" : "no");
map_data_set_map(state, set_data->group, set_data->set, flag,
set_data, &backend_shr_set_config_free_config);
diff --git a/tests/test26-schema-single/after.sh b/tests/test26-schema-single/after.sh
new file mode 100755
index 0000000..b3a1ae6
--- /dev/null
+++ b/tests/test26-schema-single/after.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+tmpfile=`mktemp ${TMP:-/tmp}/ldifXXXXXX`
+if test -z "$tmpfile" ; then
+ echo error creating temporary file
+fi
+trap 'rm -f "$tmpfile"' EXIT
+for base in dc=example,dc=com cn=compatpeople uid=tuser1 ; do
+ basedn="${base}${basedn:+,${basedn}}"
+ for scope in base one sub ; do
+ echo '['search -b "$basedn" -s $scope']'
+ search -b "$basedn" -s $scope | $LDIFSORT
+ done
+done
diff --git a/tests/test26-schema-single/after.txt b/tests/test26-schema-single/after.txt
new file mode 100644
index 0000000..4d0db8d
--- /dev/null
+++ b/tests/test26-schema-single/after.txt
@@ -0,0 +1,266 @@
+[search -b dc=example,dc=com -s base]
+dn: dc=example,dc=com
+objectClass: top
+objectClass: domain
+dc: example
+
+[search -b dc=example,dc=com -s one]
+dn: cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Accounts
+
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+dn: cn=ipServices,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: ipServices
+
+[search -b dc=example,dc=com -s sub]
+dn: cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Accounts
+
+dn: cn=Groups1,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Groups1
+
+dn: cn=Groups2,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Groups2
+
+dn: cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Users1
+
+dn: cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Users2
+
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+dn: cn=ipServices,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: ipServices
+
+dn: cn=users,cn=Accounts,dc=example,dc=com
+objectClass: top
+objectClass: nsContainer
+cn: users
+
+dn: dc=example,dc=com
+objectClass: top
+objectClass: domain
+dc: example
+
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+dn: uid=tuser1,cn=users,cn=Accounts,dc=example,dc=com
+uid: tuser1
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1003
+gecos: tuser1
+sn: User
+homeDirectory: /home/tuser1
+cn: Tim User
+uidNumber: 1101
+
+dn: uid=tuser3,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timothy User
+cn: Timothy User
+uidNumber: 1103
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser3
+uid: tuser3
+
+dn: uid=tuser3,cn=users,cn=Accounts,dc=example,dc=com
+uid: tuser3
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1004
+gecos: tuser3
+sn: User
+homeDirectory: /home/tuser3
+cn: Timothy User
+uidNumber: 1103
+
+dn: uid=user1a,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user1a
+uidNumber: 1001
+gidNumber: 1001
+cn: User 1 A
+gecos: User 1 A
+loginShell: /bin/sh
+homeDirectory: /home/user1a
+
+dn: uid=user1b,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user1b
+uidNumber: 1002
+gidNumber: 1002
+cn: User 1 B
+gecos: User 1 B
+loginShell: /bin/sh
+homeDirectory: /home/user1b
+
+dn: uid=user1c,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user1c
+uidNumber: 1003
+gidNumber: 1003
+cn: User 1 C
+gecos: User 1 C
+loginShell: /bin/sh
+homeDirectory: /home/user1c
+
+dn: uid=user2a,cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user2a
+uidNumber: 2001
+gidNumber: 2001
+cn: User 2 A
+gecos: User 2 A
+loginShell: /bin/sh
+homeDirectory: /home/user2a
+
+dn: uid=user2b,cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user2b
+uidNumber: 2002
+gidNumber: 2002
+cn: User 2 B
+gecos: User 2 B
+loginShell: /bin/sh
+homeDirectory: /home/user2b
+
+dn: uid=user2c,cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user2c
+uidNumber: 2003
+gidNumber: 2003
+cn: User 2 C
+gecos: User 2 C
+loginShell: /bin/sh
+homeDirectory: /home/user2c
+
+[search -b cn=compatpeople,dc=example,dc=com -s base]
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+[search -b cn=compatpeople,dc=example,dc=com -s one]
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+dn: uid=tuser3,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timothy User
+cn: Timothy User
+uidNumber: 1103
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser3
+uid: tuser3
+
+[search -b cn=compatpeople,dc=example,dc=com -s sub]
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+dn: uid=tuser3,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timothy User
+cn: Timothy User
+uidNumber: 1103
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser3
+uid: tuser3
+
+[search -b uid=tuser1,cn=compatpeople,dc=example,dc=com -s base]
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+[search -b uid=tuser1,cn=compatpeople,dc=example,dc=com -s one]
+[search -b uid=tuser1,cn=compatpeople,dc=example,dc=com -s sub]
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
diff --git a/tests/test26-schema-single/before.sh b/tests/test26-schema-single/before.sh
new file mode 100755
index 0000000..b3a1ae6
--- /dev/null
+++ b/tests/test26-schema-single/before.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+tmpfile=`mktemp ${TMP:-/tmp}/ldifXXXXXX`
+if test -z "$tmpfile" ; then
+ echo error creating temporary file
+fi
+trap 'rm -f "$tmpfile"' EXIT
+for base in dc=example,dc=com cn=compatpeople uid=tuser1 ; do
+ basedn="${base}${basedn:+,${basedn}}"
+ for scope in base one sub ; do
+ echo '['search -b "$basedn" -s $scope']'
+ search -b "$basedn" -s $scope | $LDIFSORT
+ done
+done
diff --git a/tests/test26-schema-single/before.txt b/tests/test26-schema-single/before.txt
new file mode 100644
index 0000000..ab77be8
--- /dev/null
+++ b/tests/test26-schema-single/before.txt
@@ -0,0 +1,312 @@
+[search -b dc=example,dc=com -s base]
+dn: dc=example,dc=com
+objectClass: top
+objectClass: domain
+dc: example
+
+[search -b dc=example,dc=com -s one]
+dn: cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Accounts
+
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+dn: cn=ipServices,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: ipServices
+
+[search -b dc=example,dc=com -s sub]
+dn: cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Accounts
+
+dn: cn=Groups1,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Groups1
+
+dn: cn=Groups2,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Groups2
+
+dn: cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Users1
+
+dn: cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: Users2
+
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+dn: cn=ipServices,dc=example,dc=com
+objectClass: nsContainer
+objectClass: top
+cn: ipServices
+
+dn: cn=users,cn=Accounts,dc=example,dc=com
+objectClass: top
+objectClass: nsContainer
+cn: users
+
+dn: dc=example,dc=com
+objectClass: top
+objectClass: domain
+dc: example
+
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+dn: uid=tuser1,cn=users,cn=Accounts,dc=example,dc=com
+uid: tuser1
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1003
+gecos: tuser1
+sn: User
+homeDirectory: /home/tuser1
+cn: Tim User
+uidNumber: 1101
+
+dn: uid=tuser2,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timmy User
+cn: Timmy User
+uidNumber: 1102
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser2
+uid: tuser2
+
+dn: uid=tuser2,cn=users,cn=Accounts,dc=example,dc=com
+uid: tuser2
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1004
+gecos: tuser2
+sn: User
+homeDirectory: /home/tuser2
+cn: Timmy User
+uidNumber: 1102
+
+dn: uid=tuser3,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timothy User
+cn: Timothy User
+uidNumber: 1103
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser3
+uid: tuser3
+
+dn: uid=tuser3,cn=users,cn=Accounts,dc=example,dc=com
+uid: tuser3
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1004
+gecos: tuser3
+sn: User
+homeDirectory: /home/tuser3
+cn: Timothy User
+uidNumber: 1103
+
+dn: uid=user1a,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user1a
+uidNumber: 1001
+gidNumber: 1001
+cn: User 1 A
+gecos: User 1 A
+loginShell: /bin/sh
+homeDirectory: /home/user1a
+
+dn: uid=user1b,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user1b
+uidNumber: 1002
+gidNumber: 1002
+cn: User 1 B
+gecos: User 1 B
+loginShell: /bin/sh
+homeDirectory: /home/user1b
+
+dn: uid=user1c,cn=Users1,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user1c
+uidNumber: 1003
+gidNumber: 1003
+cn: User 1 C
+gecos: User 1 C
+loginShell: /bin/sh
+homeDirectory: /home/user1c
+
+dn: uid=user2a,cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user2a
+uidNumber: 2001
+gidNumber: 2001
+cn: User 2 A
+gecos: User 2 A
+loginShell: /bin/sh
+homeDirectory: /home/user2a
+
+dn: uid=user2b,cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user2b
+uidNumber: 2002
+gidNumber: 2002
+cn: User 2 B
+gecos: User 2 B
+loginShell: /bin/sh
+homeDirectory: /home/user2b
+
+dn: uid=user2c,cn=Users2,cn=Accounts,dc=example,dc=com
+objectClass: posixAccount
+objectClass: inetUser
+objectClass: top
+uid: user2c
+uidNumber: 2003
+gidNumber: 2003
+cn: User 2 C
+gecos: User 2 C
+loginShell: /bin/sh
+homeDirectory: /home/user2c
+
+[search -b cn=compatpeople,dc=example,dc=com -s base]
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+[search -b cn=compatpeople,dc=example,dc=com -s one]
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+dn: uid=tuser2,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timmy User
+cn: Timmy User
+uidNumber: 1102
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser2
+uid: tuser2
+
+dn: uid=tuser3,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timothy User
+cn: Timothy User
+uidNumber: 1103
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser3
+uid: tuser3
+
+[search -b cn=compatpeople,dc=example,dc=com -s sub]
+dn: cn=compatpeople, dc=example, dc=com
+objectClass: extensibleObject
+cn: compatpeople
+
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+dn: uid=tuser2,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timmy User
+cn: Timmy User
+uidNumber: 1102
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser2
+uid: tuser2
+
+dn: uid=tuser3,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Timothy User
+cn: Timothy User
+uidNumber: 1103
+gidNumber: 1004
+loginShell: /bin/sh
+homeDirectory: /home/tuser3
+uid: tuser3
+
+[search -b uid=tuser1,cn=compatpeople,dc=example,dc=com -s base]
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
+[search -b uid=tuser1,cn=compatpeople,dc=example,dc=com -s one]
+[search -b uid=tuser1,cn=compatpeople,dc=example,dc=com -s sub]
+dn: uid=tuser1,cn=compatpeople,dc=example,dc=com
+objectClass: posixAccount
+objectClass: top
+gecos: Tim User
+cn: Tim User
+uidNumber: 1101
+gidNumber: 1003
+loginShell: /bin/sh
+homeDirectory: /home/tuser1
+uid: tuser1
+
diff --git a/tests/test26-schema-single/change.sh b/tests/test26-schema-single/change.sh
new file mode 100755
index 0000000..1714104
--- /dev/null
+++ b/tests/test26-schema-single/change.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+delete "uid=tuser2, cn=users, cn=accounts, dc=example, dc=com"
diff --git a/tests/test26-schema-single/change.txt b/tests/test26-schema-single/change.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/test26-schema-single/change.txt
diff --git a/tests/test26-schema-single/description.txt b/tests/test26-schema-single/description.txt
new file mode 100644
index 0000000..2cd3ac3
--- /dev/null
+++ b/tests/test26-schema-single/description.txt
@@ -0,0 +1 @@
+single-container with no RDN
diff --git a/tests/test26-schema-single/dse.ldif b/tests/test26-schema-single/dse.ldif
new file mode 100644
index 0000000..87adac9
--- /dev/null
+++ b/tests/test26-schema-single/dse.ldif
@@ -0,0 +1,16 @@
+dn: ou=people, cn=Schema Compatibility, cn=plugins, cn=config
+objectClass: top
+objectClass: extensibleObject
+ou: people
+schema-compat-container-group: cn=compatpeople, dc=example, dc=com
+schema-compat-search-base: cn=Users, cn=Accounts, dc=example, dc=com
+schema-compat-search-filter: objectclass=posixAccount
+schema-compat-entry-rdn: uid=%{uid}
+schema-compat-entry-attribute: objectclass=posixAccount
+schema-compat-entry-attribute: gecos=%{cn}
+schema-compat-entry-attribute: cn=%{cn}
+schema-compat-entry-attribute: uidNumber=%{uidNumber}
+schema-compat-entry-attribute: gidNumber=%{gidNumber}
+schema-compat-entry-attribute: loginShell=%{loginShell}
+schema-compat-entry-attribute: homeDirectory=%{homeDirectory}
+
diff --git a/tests/test26-schema-single/userRoot.ldif b/tests/test26-schema-single/userRoot.ldif
new file mode 100644
index 0000000..d8fd348
--- /dev/null
+++ b/tests/test26-schema-single/userRoot.ldif
@@ -0,0 +1,48 @@
+# users, accounts, example.com
+dn: cn=users,cn=accounts,dc=example,dc=com
+objectClass: top
+objectClass: nsContainer
+cn: users
+
+# tuser1, users, accounts, example.com
+dn: uid=tuser1,cn=users,cn=accounts,dc=example,dc=com
+uid: tuser1
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1003
+gecos: tuser1
+sn: User
+homeDirectory: /home/tuser1
+cn: Tim User
+uidNumber: 1101
+
+# tuser2, users, accounts, example.com
+dn: uid=tuser2,cn=users,cn=accounts,dc=example,dc=com
+uid: tuser2
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1004
+gecos: tuser2
+sn: User
+homeDirectory: /home/tuser2
+cn: Timmy User
+uidNumber: 1102
+
+# tuser3, users, accounts, example.com
+dn: uid=tuser3,cn=users,cn=accounts,dc=example,dc=com
+uid: tuser3
+objectClass: top
+objectClass: person
+objectClass: posixAccount
+loginShell: /bin/sh
+gidNumber: 1004
+gecos: tuser3
+sn: User
+homeDirectory: /home/tuser3
+cn: Timothy User
+uidNumber: 1103
+