summaryrefslogtreecommitdiffstats
path: root/source4/torture/drs/unit
diff options
context:
space:
mode:
Diffstat (limited to 'source4/torture/drs/unit')
-rw-r--r--source4/torture/drs/unit/prefixmap_tests.c900
-rw-r--r--source4/torture/drs/unit/schemainfo_tests.c740
2 files changed, 1640 insertions, 0 deletions
diff --git a/source4/torture/drs/unit/prefixmap_tests.c b/source4/torture/drs/unit/prefixmap_tests.c
new file mode 100644
index 0000000..35764cd
--- /dev/null
+++ b/source4/torture/drs/unit/prefixmap_tests.c
@@ -0,0 +1,900 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ DRSUAPI prefixMap unit tests
+
+ Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2009-2010
+
+ 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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "torture/smbtorture.h"
+#include "dsdb/samdb/samdb.h"
+#include "torture/rpc/drsuapi.h"
+#include "torture/drs/proto.h"
+#include "param/param.h"
+#include "librpc/ndr/libndr.h"
+
+/**
+ * Private data to be shared among all test in Test case
+ */
+struct drsut_prefixmap_data {
+ struct dsdb_schema_prefixmap *pfm_new;
+ struct dsdb_schema_prefixmap *pfm_full;
+
+ /* default schemaInfo value to test with */
+ struct dsdb_schema_info *schi_default;
+
+ struct ldb_context *ldb_ctx;
+};
+
+/**
+ * Test-oid data structure
+ */
+struct drsut_pfm_oid_data {
+ uint32_t id;
+ const char *bin_oid;
+ const char *oid_prefix;
+};
+
+/**
+ * Default prefixMap initialization data.
+ * This prefixMap is what dsdb_schema_pfm_new() should return.
+ * Based on: MS-DRSR, 5.16.4 ATTRTYP-to-OID Conversion
+ * procedure NewPrefixTable( )
+ */
+static const struct drsut_pfm_oid_data _prefixmap_test_new_data[] = {
+ {.id=0x00000000, .bin_oid="5504", .oid_prefix="2.5.4"},
+ {.id=0x00000001, .bin_oid="5506", .oid_prefix="2.5.6"},
+ {.id=0x00000002, .bin_oid="2A864886F7140102", .oid_prefix="1.2.840.113556.1.2"},
+ {.id=0x00000003, .bin_oid="2A864886F7140103", .oid_prefix="1.2.840.113556.1.3"},
+ {.id=0x00000004, .bin_oid="6086480165020201", .oid_prefix="2.16.840.1.101.2.2.1"},
+ {.id=0x00000005, .bin_oid="6086480165020203", .oid_prefix="2.16.840.1.101.2.2.3"},
+ {.id=0x00000006, .bin_oid="6086480165020105", .oid_prefix="2.16.840.1.101.2.1.5"},
+ {.id=0x00000007, .bin_oid="6086480165020104", .oid_prefix="2.16.840.1.101.2.1.4"},
+ {.id=0x00000008, .bin_oid="5505", .oid_prefix="2.5.5"},
+ {.id=0x00000009, .bin_oid="2A864886F7140104", .oid_prefix="1.2.840.113556.1.4"},
+ {.id=0x0000000A, .bin_oid="2A864886F7140105", .oid_prefix="1.2.840.113556.1.5"},
+ {.id=0x00000013, .bin_oid="0992268993F22C64", .oid_prefix="0.9.2342.19200300.100"},
+ {.id=0x00000014, .bin_oid="6086480186F84203", .oid_prefix="2.16.840.1.113730.3"},
+ {.id=0x00000015, .bin_oid="0992268993F22C6401", .oid_prefix="0.9.2342.19200300.100.1"},
+ {.id=0x00000016, .bin_oid="6086480186F8420301", .oid_prefix="2.16.840.1.113730.3.1"},
+ {.id=0x00000017, .bin_oid="2A864886F7140105B658", .oid_prefix="1.2.840.113556.1.5.7000"},
+ {.id=0x00000018, .bin_oid="5515", .oid_prefix="2.5.21"},
+ {.id=0x00000019, .bin_oid="5512", .oid_prefix="2.5.18"},
+ {.id=0x0000001A, .bin_oid="5514", .oid_prefix="2.5.20"},
+};
+
+/**
+ * Data to be used for creating full prefix map for testing.
+ * 'full-prefixMap' is based on what w2k8 returns as a prefixMap
+ * on clean installation - i.e. prefixMap for clean Schema
+ */
+static const struct drsut_pfm_oid_data _prefixmap_full_map_data[] = {
+ {.id=0x00000000, .bin_oid="0x5504", .oid_prefix="2.5.4"},
+ {.id=0x00000001, .bin_oid="0x5506", .oid_prefix="2.5.6"},
+ {.id=0x00000002, .bin_oid="0x2A864886F7140102", .oid_prefix="1.2.840.113556.1.2"},
+ {.id=0x00000003, .bin_oid="0x2A864886F7140103", .oid_prefix="1.2.840.113556.1.3"},
+ {.id=0x00000004, .bin_oid="0x6086480165020201", .oid_prefix="2.16.840.1.101.2.2.1"},
+ {.id=0x00000005, .bin_oid="0x6086480165020203", .oid_prefix="2.16.840.1.101.2.2.3"},
+ {.id=0x00000006, .bin_oid="0x6086480165020105", .oid_prefix="2.16.840.1.101.2.1.5"},
+ {.id=0x00000007, .bin_oid="0x6086480165020104", .oid_prefix="2.16.840.1.101.2.1.4"},
+ {.id=0x00000008, .bin_oid="0x5505", .oid_prefix="2.5.5"},
+ {.id=0x00000009, .bin_oid="0x2A864886F7140104", .oid_prefix="1.2.840.113556.1.4"},
+ {.id=0x0000000a, .bin_oid="0x2A864886F7140105", .oid_prefix="1.2.840.113556.1.5"},
+ {.id=0x00000013, .bin_oid="0x0992268993F22C64", .oid_prefix="0.9.2342.19200300.100"},
+ {.id=0x00000014, .bin_oid="0x6086480186F84203", .oid_prefix="2.16.840.1.113730.3"},
+ {.id=0x00000015, .bin_oid="0x0992268993F22C6401", .oid_prefix="0.9.2342.19200300.100.1"},
+ {.id=0x00000016, .bin_oid="0x6086480186F8420301", .oid_prefix="2.16.840.1.113730.3.1"},
+ {.id=0x00000017, .bin_oid="0x2A864886F7140105B658", .oid_prefix="1.2.840.113556.1.5.7000"},
+ {.id=0x00000018, .bin_oid="0x5515", .oid_prefix="2.5.21"},
+ {.id=0x00000019, .bin_oid="0x5512", .oid_prefix="2.5.18"},
+ {.id=0x0000001a, .bin_oid="0x5514", .oid_prefix="2.5.20"},
+ {.id=0x0000000b, .bin_oid="0x2A864886F71401048204", .oid_prefix="1.2.840.113556.1.4.260"},
+ {.id=0x0000000c, .bin_oid="0x2A864886F714010538", .oid_prefix="1.2.840.113556.1.5.56"},
+ {.id=0x0000000d, .bin_oid="0x2A864886F71401048206", .oid_prefix="1.2.840.113556.1.4.262"},
+ {.id=0x0000000e, .bin_oid="0x2A864886F714010539", .oid_prefix="1.2.840.113556.1.5.57"},
+ {.id=0x0000000f, .bin_oid="0x2A864886F71401048207", .oid_prefix="1.2.840.113556.1.4.263"},
+ {.id=0x00000010, .bin_oid="0x2A864886F71401053A", .oid_prefix="1.2.840.113556.1.5.58"},
+ {.id=0x00000011, .bin_oid="0x2A864886F714010549", .oid_prefix="1.2.840.113556.1.5.73"},
+ {.id=0x00000012, .bin_oid="0x2A864886F71401048231", .oid_prefix="1.2.840.113556.1.4.305"},
+ {.id=0x0000001b, .bin_oid="0x2B060104018B3A6577", .oid_prefix="1.3.6.1.4.1.1466.101.119"},
+ {.id=0x0000001c, .bin_oid="0x6086480186F8420302", .oid_prefix="2.16.840.1.113730.3.2"},
+ {.id=0x0000001d, .bin_oid="0x2B06010401817A01", .oid_prefix="1.3.6.1.4.1.250.1"},
+ {.id=0x0000001e, .bin_oid="0x2A864886F70D0109", .oid_prefix="1.2.840.113549.1.9"},
+ {.id=0x0000001f, .bin_oid="0x0992268993F22C6404", .oid_prefix="0.9.2342.19200300.100.4"},
+ {.id=0x00000020, .bin_oid="0x2A864886F714010617", .oid_prefix="1.2.840.113556.1.6.23"},
+ {.id=0x00000021, .bin_oid="0x2A864886F71401061201", .oid_prefix="1.2.840.113556.1.6.18.1"},
+ {.id=0x00000022, .bin_oid="0x2A864886F71401061202", .oid_prefix="1.2.840.113556.1.6.18.2"},
+ {.id=0x00000023, .bin_oid="0x2A864886F71401060D03", .oid_prefix="1.2.840.113556.1.6.13.3"},
+ {.id=0x00000024, .bin_oid="0x2A864886F71401060D04", .oid_prefix="1.2.840.113556.1.6.13.4"},
+ {.id=0x00000025, .bin_oid="0x2B0601010101", .oid_prefix="1.3.6.1.1.1.1"},
+ {.id=0x00000026, .bin_oid="0x2B0601010102", .oid_prefix="1.3.6.1.1.1.2"},
+ {.id=0x000003ed, .bin_oid="0x2A864886F7140104B65866", .oid_prefix="1.2.840.113556.1.4.7000.102"},
+ {.id=0x00000428, .bin_oid="0x2A864886F7140105B6583E", .oid_prefix="1.2.840.113556.1.5.7000.62"},
+ {.id=0x0000044c, .bin_oid="0x2A864886F7140104B6586683", .oid_prefix="1.2.840.113556.1.4.7000.102:0x83"},
+ {.id=0x0000044f, .bin_oid="0x2A864886F7140104B6586681", .oid_prefix="1.2.840.113556.1.4.7000.102:0x81"},
+ {.id=0x0000047d, .bin_oid="0x2A864886F7140105B6583E81", .oid_prefix="1.2.840.113556.1.5.7000.62:0x81"},
+ {.id=0x00000561, .bin_oid="0x2A864886F7140105B6583E83", .oid_prefix="1.2.840.113556.1.5.7000.62:0x83"},
+ {.id=0x000007d1, .bin_oid="0x2A864886F71401061401", .oid_prefix="1.2.840.113556.1.6.20.1"},
+ {.id=0x000007e1, .bin_oid="0x2A864886F71401061402", .oid_prefix="1.2.840.113556.1.6.20.2"},
+ {.id=0x00001b86, .bin_oid="0x2A817A", .oid_prefix="1.2.250"},
+ {.id=0x00001c78, .bin_oid="0x2A817A81", .oid_prefix="1.2.250:0x81"},
+ {.id=0x00001c7b, .bin_oid="0x2A817A8180", .oid_prefix="1.2.250:0x8180"},
+};
+
+
+/**
+ * OID-to-ATTID mappings to be used for testing.
+ * An entry is marked as 'exists=true' if it exists in
+ * base prefixMap (_prefixmap_test_new_data)
+ */
+static const struct {
+ const char *oid;
+ uint32_t id;
+ uint32_t attid;
+ bool exists;
+} _prefixmap_test_data[] = {
+ {.oid="2.5.4.0", .id=0x00000000, .attid=0x000000, .exists=true},
+ {.oid="2.5.4.42", .id=0x00000000, .attid=0x00002a, .exists=true},
+ {.oid="1.2.840.113556.1.2.1", .id=0x00000002, .attid=0x020001, .exists=true},
+ {.oid="1.2.840.113556.1.2.13", .id=0x00000002, .attid=0x02000d, .exists=true},
+ {.oid="1.2.840.113556.1.2.281", .id=0x00000002, .attid=0x020119, .exists=true},
+ {.oid="1.2.840.113556.1.4.125", .id=0x00000009, .attid=0x09007d, .exists=true},
+ {.oid="1.2.840.113556.1.4.146", .id=0x00000009, .attid=0x090092, .exists=true},
+ {.oid="1.2.250.1", .id=0x00001b86, .attid=0x1b860001, .exists=false},
+ {.oid="1.2.250.16386", .id=0x00001c78, .attid=0x1c788002, .exists=false},
+ {.oid="1.2.250.2097154", .id=0x00001c7b, .attid=0x1c7b8002, .exists=false},
+};
+
+
+/**
+ * Creates dsdb_schema_prefixmap based on predefined data
+ */
+static WERROR _drsut_prefixmap_new(const struct drsut_pfm_oid_data *_pfm_init_data, uint32_t count,
+ TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
+{
+ uint32_t i;
+ struct dsdb_schema_prefixmap *pfm;
+
+ pfm = talloc(mem_ctx, struct dsdb_schema_prefixmap);
+ W_ERROR_HAVE_NO_MEMORY(pfm);
+
+ pfm->length = count;
+ pfm->prefixes = talloc_array(pfm, struct dsdb_schema_prefixmap_oid, pfm->length);
+ if (!pfm->prefixes) {
+ talloc_free(pfm);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+
+ for (i = 0; i < pfm->length; i++) {
+ pfm->prefixes[i].id = _pfm_init_data[i].id;
+ pfm->prefixes[i].bin_oid = strhex_to_data_blob(pfm, _pfm_init_data[i].bin_oid);
+ if (!pfm->prefixes[i].bin_oid.data) {
+ talloc_free(pfm);
+ return WERR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ *_pfm = pfm;
+
+ return WERR_OK;
+}
+
+/**
+ * Compares two prefixMaps for being equal - same items on same indexes
+ */
+static bool _torture_drs_pfm_compare_same(struct torture_context *tctx,
+ const struct dsdb_schema_prefixmap *pfm_left,
+ const struct dsdb_schema_prefixmap *pfm_right,
+ bool quiet)
+{
+ uint32_t i;
+ char *err_msg = NULL;
+
+ if (pfm_left->length != pfm_right->length) {
+ err_msg = talloc_asprintf(tctx, "prefixMaps differ in size; left = %d, right = %d",
+ pfm_left->length, pfm_right->length);
+ goto failed;
+ }
+
+ for (i = 0; i < pfm_left->length; i++) {
+ struct dsdb_schema_prefixmap_oid *entry_left = &pfm_left->prefixes[i];
+ struct dsdb_schema_prefixmap_oid *entry_right = &pfm_right->prefixes[i];
+
+ if (entry_left->id != entry_right->id) {
+ err_msg = talloc_asprintf(tctx, "Different IDs for index=%d", i);
+ goto failed;
+ }
+ if (data_blob_cmp(&entry_left->bin_oid, &entry_right->bin_oid)) {
+ err_msg = talloc_asprintf(tctx, "Different bin_oid for index=%d", i);
+ goto failed;
+ }
+ }
+
+ return true;
+
+failed:
+ if (!quiet) {
+ torture_comment(tctx, "_torture_drs_pfm_compare_same: %s", err_msg);
+ }
+ talloc_free(err_msg);
+
+ return false;
+}
+
+/*
+ * Tests dsdb_schema_pfm_new()
+ */
+static bool torture_drs_unit_pfm_new(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ bool bret;
+ TALLOC_CTX *mem_ctx;
+ struct dsdb_schema_prefixmap *pfm = NULL;
+
+ mem_ctx = talloc_new(priv);
+
+ /* create new prefix map */
+ werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
+ torture_assert(tctx, pfm != NULL, "NULL prefixMap created!");
+ torture_assert(tctx, pfm->length > 0, "Empty prefixMap created!");
+ torture_assert(tctx, pfm->prefixes != NULL, "No prefixes for newly created prefixMap!");
+
+ /* compare newly created prefixMap with template one */
+ bret = _torture_drs_pfm_compare_same(tctx, priv->pfm_new, pfm, false);
+
+ talloc_free(mem_ctx);
+
+ return bret;
+}
+
+/**
+ * Tests dsdb_schema_pfm_make_attid() using full prefixMap.
+ * In this test we know exactly which ATTID and prefixMap->ID
+ * should be returned, i.e. no prefixMap entries should be added.
+ */
+static bool torture_drs_unit_pfm_make_attid_full_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ uint32_t i, count;
+ uint32_t attid;
+ char *err_msg;
+
+ count = ARRAY_SIZE(_prefixmap_test_data);
+ for (i = 0; i < count; i++) {
+ werr = dsdb_schema_pfm_make_attid(priv->pfm_full, _prefixmap_test_data[i].oid, &attid);
+ /* prepare error message */
+ err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_make_attid() failed with %s",
+ _prefixmap_test_data[i].oid);
+ torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
+ /* verify result and returned ATTID */
+ torture_assert_werr_ok(tctx, werr, err_msg);
+ torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg);
+ /* reclaim memory for prepared error message */
+ talloc_free(err_msg);
+ }
+
+ return true;
+}
+
+/**
+ * Tests dsdb_schema_pfm_make_attid() using initially small prefixMap.
+ * In this test we don't know exactly which ATTID and prefixMap->ID
+ * should be returned, but we can verify lo-word of ATTID.
+ * This test verifies implementation branch when a new
+ * prefix should be added into prefixMap.
+ */
+static bool torture_drs_unit_pfm_make_attid_small_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ uint32_t i, j;
+ uint32_t idx;
+ uint32_t attid, attid_2;
+ char *err_msg;
+ struct dsdb_schema_prefixmap *pfm = NULL;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(priv);
+
+ /* create new prefix map */
+ werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
+
+ /* make some ATTIDs and check result */
+ for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
+ werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid);
+
+ /* prepare error message */
+ err_msg = talloc_asprintf(mem_ctx, "dsdb_schema_pfm_make_attid() failed with %s",
+ _prefixmap_test_data[i].oid);
+ torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
+
+ /* verify result and returned ATTID */
+ torture_assert_werr_ok(tctx, werr, err_msg);
+ /* verify ATTID lo-word */
+ torture_assert_int_equal(tctx, attid & 0xFFFF, _prefixmap_test_data[i].attid & 0xFFFF, err_msg);
+
+ /* try again, this time verify for whole ATTID */
+ werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid_2);
+ torture_assert_werr_ok(tctx, werr, err_msg);
+ torture_assert_int_equal(tctx, attid_2, attid, err_msg);
+
+ /* reclaim memory for prepared error message */
+ talloc_free(err_msg);
+
+ /* check there is such an index in modified prefixMap */
+ idx = (attid >> 16);
+ for (j = 0; j < pfm->length; j++) {
+ if (pfm->prefixes[j].id == idx)
+ break;
+ }
+ if (j >= pfm->length) {
+ torture_result(tctx, TORTURE_FAIL, __location__": No prefix for ATTID=0x%08X", attid);
+ return false;
+ }
+
+ }
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
+/**
+ * Tests dsdb_schema_pfm_attid_from_oid() using full prefixMap.
+ * In this test we know exactly which ATTID and prefixMap->ID
+ * should be returned- dsdb_schema_pfm_attid_from_oid() should succeed.
+ */
+static bool torture_drs_unit_pfm_attid_from_oid_full_map(struct torture_context *tctx,
+ struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ uint32_t i, count;
+ uint32_t attid;
+ char *err_msg;
+
+ count = ARRAY_SIZE(_prefixmap_test_data);
+ for (i = 0; i < count; i++) {
+ werr = dsdb_schema_pfm_attid_from_oid(priv->pfm_full,
+ _prefixmap_test_data[i].oid,
+ &attid);
+ /* prepare error message */
+ err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_attid_from_oid() failed with %s",
+ _prefixmap_test_data[i].oid);
+ torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
+ /* verify result and returned ATTID */
+ torture_assert_werr_ok(tctx, werr, err_msg);
+ torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg);
+ /* reclaim memory for prepared error message */
+ talloc_free(err_msg);
+ }
+
+ return true;
+}
+
+/**
+ * Tests dsdb_schema_pfm_attid_from_oid() using base (initial) prefixMap.
+ * dsdb_schema_pfm_attid_from_oid() should fail when testing with OID
+ * that are not already in the prefixMap.
+ */
+static bool torture_drs_unit_pfm_attid_from_oid_base_map(struct torture_context *tctx,
+ struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ uint32_t i;
+ uint32_t attid;
+ char *err_msg;
+ struct dsdb_schema_prefixmap *pfm = NULL;
+ struct dsdb_schema_prefixmap pfm_prev;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(priv);
+ torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
+
+ /* create new prefix map */
+ werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
+
+ /* keep initial pfm around for testing */
+ pfm_prev = *pfm;
+ pfm_prev.prefixes = talloc_reference(mem_ctx, pfm->prefixes);
+
+ /* get some ATTIDs and check result */
+ for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
+ werr = dsdb_schema_pfm_attid_from_oid(pfm, _prefixmap_test_data[i].oid, &attid);
+
+ /* prepare error message */
+ err_msg = talloc_asprintf(mem_ctx,
+ "dsdb_schema_pfm_attid_from_oid() failed for %s",
+ _prefixmap_test_data[i].oid);
+ torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
+
+
+ /* verify pfm hasn't been altered */
+ if (_prefixmap_test_data[i].exists) {
+ /* should succeed and return valid ATTID */
+ torture_assert_werr_ok(tctx, werr, err_msg);
+ /* verify ATTID */
+ torture_assert_int_equal(tctx,
+ attid, _prefixmap_test_data[i].attid,
+ err_msg);
+ } else {
+ /* should fail */
+ torture_assert_werr_equal(tctx, werr, WERR_NOT_FOUND, err_msg);
+ }
+
+ /* prefixMap should never be changed */
+ if (!_torture_drs_pfm_compare_same(tctx, &pfm_prev, pfm, true)) {
+ torture_fail(tctx, "schema->prefixmap has changed");
+ }
+
+ /* reclaim memory for prepared error message */
+ talloc_free(err_msg);
+ }
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
+/**
+ * Tests dsdb_schema_pfm_oid_from_attid() using full prefixMap.
+ */
+static bool torture_drs_unit_pfm_oid_from_attid(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ uint32_t i, count;
+ char *err_msg;
+ const char *oid;
+
+ count = ARRAY_SIZE(_prefixmap_test_data);
+ for (i = 0; i < count; i++) {
+ oid = NULL;
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, _prefixmap_test_data[i].attid,
+ priv, &oid);
+ /* prepare error message */
+ err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_oid_from_attid() failed with 0x%08X",
+ _prefixmap_test_data[i].attid);
+ torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
+ /* verify result and returned ATTID */
+ torture_assert_werr_ok(tctx, werr, err_msg);
+ torture_assert(tctx, oid, "dsdb_schema_pfm_oid_from_attid() returned NULL OID!!!");
+ torture_assert_str_equal(tctx, oid, _prefixmap_test_data[i].oid, err_msg);
+ /* reclaim memory for prepared error message */
+ talloc_free(err_msg);
+ /* free memory for OID */
+ talloc_free(discard_const(oid));
+ }
+
+ return true;
+}
+
+/**
+ * Tests dsdb_schema_pfm_oid_from_attid() for handling
+ * correctly different type of attid values.
+ * See: MS-ADTS, 3.1.1.2.6 ATTRTYP
+ */
+static bool torture_drs_unit_pfm_oid_from_attid_check_attid(struct torture_context *tctx,
+ struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ const char *oid;
+
+ /* Test with valid prefixMap attid */
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x00010001, tctx, &oid);
+ torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x00010001");
+
+ /* Test with valid attid but invalid index */
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x01110001, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE,
+ "Testing invalid-index attid = 0x01110001");
+
+ /* Test with attid in msDS-IntId range */
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x80000000, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
+ "Testing msDS-IntId type attid = 0x80000000");
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xBFFFFFFF, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
+ "Testing msDS-IntId type attid = 0xBFFFFFFF");
+
+ /* Test with attid in RESERVED range */
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xC0000000, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
+ "Testing RESERVED type attid = 0xC0000000");
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFEFFFF, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
+ "Testing RESERVED type attid = 0xFFFEFFFF");
+
+ /* Test with attid in INTERNAL range */
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFF0000, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
+ "Testing INTERNAL type attid = 0xFFFF0000");
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFFFFFF, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
+ "Testing INTERNAL type attid = 0xFFFFFFFF");
+
+ return true;
+}
+
+/**
+ * Test Schema prefixMap conversions to/from drsuapi prefixMap
+ * representation.
+ */
+static bool torture_drs_unit_pfm_to_from_drsuapi(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ struct dsdb_schema_info *schema_info;
+ DATA_BLOB schema_info_blob;
+ struct dsdb_schema_prefixmap *pfm;
+ struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(tctx);
+ torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
+
+ /* convert Schema_prefixMap to drsuapi_prefixMap */
+ werr = dsdb_drsuapi_pfm_from_schema_pfm(priv->pfm_full, priv->schi_default, mem_ctx, &ctr);
+ torture_assert_werr_ok(tctx, werr, "dsdb_drsuapi_pfm_from_schema_pfm() failed");
+ torture_assert(tctx, ctr && ctr->mappings, "drsuapi_prefixMap not constructed correctly");
+ torture_assert_int_equal(tctx, ctr->num_mappings, priv->pfm_full->length + 1,
+ "drs_mappings count does not match");
+ /* look for schema_info entry - it should be the last one */
+ schema_info_blob = data_blob_const(ctr->mappings[ctr->num_mappings - 1].oid.binary_oid,
+ ctr->mappings[ctr->num_mappings - 1].oid.length);
+ werr = dsdb_schema_info_from_blob(&schema_info_blob, tctx, &schema_info);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob failed");
+ torture_assert_int_equal(tctx, schema_info->revision, priv->schi_default->revision,
+ "schema_info (revision) not stored correctly or not last entry");
+ torture_assert(tctx, GUID_equal(&schema_info->invocation_id, &priv->schi_default->invocation_id),
+ "schema_info (invocation_id) not stored correctly or not last entry");
+
+ /* compare schema_prefixMap and drsuapi_prefixMap */
+ werr = dsdb_schema_pfm_contains_drsuapi_pfm(priv->pfm_full, ctr);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_contains_drsuapi_pfm() failed");
+
+ /* convert back drsuapi_prefixMap to schema_prefixMap */
+ werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, mem_ctx, &pfm, &schema_info);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed");
+ torture_assert_int_equal(tctx, schema_info->revision, priv->schi_default->revision,
+ "Fetched schema_info is different (revision)");
+ torture_assert(tctx, GUID_equal(&schema_info->invocation_id, &priv->schi_default->invocation_id),
+ "Fetched schema_info is different (invocation_id)");
+
+ /* compare against the original */
+ if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, true)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ /* test conversion with partial drsuapi_prefixMap */
+ ctr->num_mappings--;
+ werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, false, mem_ctx, &pfm, NULL);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed");
+ /* compare against the original */
+ if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, false)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+
+ talloc_free(mem_ctx);
+ return true;
+}
+
+
+/**
+ * Test Schema prefixMap conversions to/from ldb_val
+ * blob representation.
+ */
+static bool torture_drs_unit_pfm_to_from_ldb_val(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ struct dsdb_schema *schema;
+ struct ldb_val pfm_ldb_val;
+ struct ldb_val schema_info_ldb_val;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(tctx);
+ torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
+
+ schema = dsdb_new_schema(mem_ctx);
+ torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
+
+ /* set priv->pfm_full as prefixMap for new schema object */
+ schema->prefixmap = priv->pfm_full;
+ schema->schema_info = priv->schi_default;
+
+ /* convert schema_prefixMap to ldb_val blob */
+ werr = dsdb_get_oid_mappings_ldb(schema, mem_ctx, &pfm_ldb_val, &schema_info_ldb_val);
+ torture_assert_werr_ok(tctx, werr, "dsdb_get_oid_mappings_ldb() failed");
+ torture_assert(tctx, pfm_ldb_val.data && pfm_ldb_val.length,
+ "pfm_ldb_val not constructed correctly");
+ torture_assert(tctx, schema_info_ldb_val.data && schema_info_ldb_val.length,
+ "schema_info_ldb_val not constructed correctly");
+
+ /* convert pfm_ldb_val back to schema_prefixMap */
+ schema->prefixmap = NULL;
+ schema->schema_info = NULL;
+ werr = dsdb_load_oid_mappings_ldb(schema, &pfm_ldb_val, &schema_info_ldb_val);
+ torture_assert_werr_ok(tctx, werr, "dsdb_load_oid_mappings_ldb() failed");
+ /* compare against the original */
+ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
+ talloc_free(mem_ctx);
+ return false;
+ }
+ torture_assert_int_equal(tctx, schema->schema_info->revision, priv->schi_default->revision,
+ "Fetched schema_info is different (revision)");
+ torture_assert(tctx, GUID_equal(&schema->schema_info->invocation_id, &priv->schi_default->invocation_id),
+ "Fetched schema_info is different (invocation_id)");
+
+ talloc_free(mem_ctx);
+ return true;
+}
+
+/**
+ * Test read/write in ldb implementation
+ */
+static bool torture_drs_unit_pfm_read_write_ldb(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ struct dsdb_schema *schema;
+ struct dsdb_schema_prefixmap *pfm;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(tctx);
+ torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
+
+ /* makeup a dsdb_schema to test with */
+ schema = dsdb_new_schema(mem_ctx);
+ torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
+ /* set priv->pfm_full as prefixMap for new schema object */
+ schema->prefixmap = priv->pfm_full;
+ schema->schema_info = priv->schi_default;
+
+ /* write prfixMap to ldb */
+ werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
+ torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
+
+ /* read from ldb what we have written */
+ werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm);
+ torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
+
+ /* compare data written/read */
+ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
+ torture_fail(tctx, "prefixMap read/write in LDB is not consistent");
+ }
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
+/**
+ * Test dsdb_create_prefix_mapping
+ */
+static bool torture_drs_unit_dsdb_create_prefix_mapping(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ WERROR werr;
+ uint32_t i;
+ struct dsdb_schema *schema;
+ TALLOC_CTX *mem_ctx;
+ struct dsdb_schema_prefixmap *pfm_ldb = NULL;
+
+ mem_ctx = talloc_new(tctx);
+ torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
+
+ /* makeup a dsdb_schema to test with */
+ schema = dsdb_new_schema(mem_ctx);
+ torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
+ /* set priv->pfm_full as prefixMap for new schema object */
+ schema->schema_info = priv->schi_default;
+ werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data),
+ schema, &schema->prefixmap);
+ torture_assert_werr_ok(tctx, werr, "_drsut_prefixmap_new() failed");
+ /* write prfixMap to ldb */
+ werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
+ torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
+
+ /* read from ldb what we have written */
+ werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb);
+ torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
+ /* compare data written/read */
+ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, pfm_ldb, true)) {
+ torture_fail(tctx, "pfm in LDB is different");
+ }
+ TALLOC_FREE(pfm_ldb);
+
+ for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
+ struct dsdb_schema_prefixmap *pfm_prev;
+ struct dsdb_schema_prefixmap *pfm_new;
+
+ pfm_prev = schema->prefixmap;
+
+ pfm_new = dsdb_schema_pfm_copy_shallow(schema, pfm_prev);
+ torture_assert(tctx, pfm_new != NULL, "dsdb_schema_pfm_copy_shallow() failed");
+
+ if (!_prefixmap_test_data[i].exists) {
+ uint32_t attid;
+
+ werr = dsdb_schema_pfm_make_attid(pfm_new,
+ _prefixmap_test_data[i].oid,
+ &attid);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_make_attid() failed");
+ }
+
+ /* call dsdb_create_prefix_mapping() and check result accordingly */
+ werr = dsdb_create_prefix_mapping(priv->ldb_ctx, schema, _prefixmap_test_data[i].oid);
+ torture_assert_werr_ok(tctx, werr, "dsdb_create_prefix_mapping() failed");
+
+ /*
+ * The prefix should not change, only on reload
+ */
+ torture_assert(tctx, pfm_prev == schema->prefixmap,
+ "schema->prefixmap has been reallocated!");
+ if (!_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
+ torture_fail(tctx, "schema->prefixmap has changed");
+ }
+
+ /* read from ldb what we have written */
+ werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb);
+ torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
+ /* compare data written/read */
+ if (!_torture_drs_pfm_compare_same(tctx, pfm_new, pfm_ldb, true)) {
+ torture_fail(tctx, talloc_asprintf(tctx, "%u: pfm in LDB is different", i));
+ }
+ /* free mem for pfm read from LDB */
+ TALLOC_FREE(pfm_ldb);
+
+ /* prepare for the next round */
+ schema->prefixmap = pfm_new;
+ }
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
+/**
+ * Prepare temporary LDB and opens it
+ */
+static bool torture_drs_unit_ldb_setup(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ int ldb_err;
+ char *ldb_url;
+ bool bret = true;
+ TALLOC_CTX* mem_ctx;
+ char *tempdir;
+ NTSTATUS status;
+
+ mem_ctx = talloc_new(priv);
+
+ status = torture_temp_dir(tctx, "drs_", &tempdir);
+ torture_assert_ntstatus_ok(tctx, status, "creating temp dir");
+
+ ldb_url = talloc_asprintf(priv, "%s/drs_test.ldb", tempdir);
+
+ /* create LDB */
+ priv->ldb_ctx = ldb_init(priv, tctx->ev);
+ ldb_err = ldb_connect(priv->ldb_ctx, ldb_url, 0, NULL);
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_connect() failed");
+
+ /* set some schemaNamingContext */
+ ldb_err = ldb_set_opaque(priv->ldb_ctx,
+ "schemaNamingContext",
+ ldb_dn_new(priv->ldb_ctx, priv->ldb_ctx, "CN=Schema,CN=Config"));
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_set_opaque() failed");
+
+ /* add prefixMap attribute so tested layer could work properly */
+ {
+ struct ldb_message *msg = ldb_msg_new(mem_ctx);
+ msg->dn = ldb_get_schema_basedn(priv->ldb_ctx);
+ ldb_err = ldb_msg_add_string(msg, "prefixMap", "prefixMap");
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
+ "ldb_msg_add_string() failed");
+
+ ldb_err = ldb_add(priv->ldb_ctx, msg);
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_add() failed");
+ }
+
+DONE:
+ talloc_free(mem_ctx);
+ return bret;
+}
+
+/*
+ * Setup/Teardown for test case
+ */
+static bool torture_drs_unit_prefixmap_setup(struct torture_context *tctx, struct drsut_prefixmap_data **_priv)
+{
+ WERROR werr;
+ DATA_BLOB blob;
+ struct drsut_prefixmap_data *priv;
+
+ priv = *_priv = talloc_zero(tctx, struct drsut_prefixmap_data);
+ torture_assert(tctx, priv != NULL, "Not enough memory");
+
+ werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data),
+ tctx, &priv->pfm_new);
+ torture_assert_werr_ok(tctx, werr, "failed to create pfm_new");
+
+ werr = _drsut_prefixmap_new(_prefixmap_full_map_data, ARRAY_SIZE(_prefixmap_full_map_data),
+ tctx, &priv->pfm_full);
+ torture_assert_werr_ok(tctx, werr, "failed to create pfm_test");
+
+ torture_assert(tctx, drsut_schemainfo_new(tctx, &priv->schi_default),
+ "drsut_schemainfo_new() failed");
+
+ werr = dsdb_blob_from_schema_info(priv->schi_default, priv, &blob);
+ torture_assert_werr_ok(tctx, werr, "dsdb_blob_from_schema_info() failed");
+
+ /* create temporary LDB and populate with data */
+ if (!torture_drs_unit_ldb_setup(tctx, priv)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool torture_drs_unit_prefixmap_teardown(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
+{
+ talloc_free(priv);
+
+ return true;
+}
+
+/**
+ * Test case initialization for
+ * drs.unit.prefixMap
+ */
+struct torture_tcase * torture_drs_unit_prefixmap(struct torture_suite *suite)
+{
+ typedef bool (*pfn_setup)(struct torture_context *, void **);
+ typedef bool (*pfn_teardown)(struct torture_context *, void *);
+ typedef bool (*pfn_run)(struct torture_context *, void *);
+
+ struct torture_tcase * tc = torture_suite_add_tcase(suite, "prefixMap");
+
+ torture_tcase_set_fixture(tc,
+ (pfn_setup)torture_drs_unit_prefixmap_setup,
+ (pfn_teardown)torture_drs_unit_prefixmap_teardown);
+
+ tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::prefixMap implementation");
+
+ torture_tcase_add_simple_test(tc, "new", (pfn_run)torture_drs_unit_pfm_new);
+
+ torture_tcase_add_simple_test(tc, "make_attid_full_map", (pfn_run)torture_drs_unit_pfm_make_attid_full_map);
+ torture_tcase_add_simple_test(tc, "make_attid_small_map", (pfn_run)torture_drs_unit_pfm_make_attid_small_map);
+
+ torture_tcase_add_simple_test(tc, "attid_from_oid_full_map",
+ (pfn_run)torture_drs_unit_pfm_attid_from_oid_full_map);
+ torture_tcase_add_simple_test(tc, "attid_from_oid_empty_map",
+ (pfn_run)torture_drs_unit_pfm_attid_from_oid_base_map);
+
+ torture_tcase_add_simple_test(tc, "oid_from_attid_full_map", (pfn_run)torture_drs_unit_pfm_oid_from_attid);
+ torture_tcase_add_simple_test(tc, "oid_from_attid_check_attid",
+ (pfn_run)torture_drs_unit_pfm_oid_from_attid_check_attid);
+
+ torture_tcase_add_simple_test(tc, "pfm_to_from_drsuapi", (pfn_run)torture_drs_unit_pfm_to_from_drsuapi);
+
+ torture_tcase_add_simple_test(tc, "pfm_to_from_ldb_val", (pfn_run)torture_drs_unit_pfm_to_from_ldb_val);
+
+ torture_tcase_add_simple_test(tc, "pfm_read_write_ldb", (pfn_run)torture_drs_unit_pfm_read_write_ldb);
+
+ torture_tcase_add_simple_test(tc, "dsdb_create_prefix_mapping", (pfn_run)torture_drs_unit_dsdb_create_prefix_mapping);
+
+ return tc;
+}
diff --git a/source4/torture/drs/unit/schemainfo_tests.c b/source4/torture/drs/unit/schemainfo_tests.c
new file mode 100644
index 0000000..4b4cca6
--- /dev/null
+++ b/source4/torture/drs/unit/schemainfo_tests.c
@@ -0,0 +1,740 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ DRSUAPI schemaInfo unit tests
+
+ Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
+
+ 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
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "torture/smbtorture.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "ldb_wrap.h"
+#include <ldb_module.h>
+#include "torture/rpc/drsuapi.h"
+#include "librpc/ndr/libndr.h"
+#include "param/param.h"
+#include "torture/drs/proto.h"
+#include "torture/drs/proto.h"
+
+
+/**
+ * schemaInfo to init ldb context with
+ * Rev: 0
+ * GUID: 00000000-0000-0000-0000-000000000000
+ */
+#define SCHEMA_INFO_INIT_STR "FF0000000000000000000000000000000000000000"
+
+/**
+ * Default schema_info string to be used for testing
+ * Rev: 01
+ * GUID: 071c82fd-45c7-4351-a3db-51f75a630a7f
+ */
+#define SCHEMA_INFO_DEFAULT_STR "FF00000001FD821C07C7455143A3DB51F75A630A7F"
+
+/**
+ * Schema info data to test with
+ */
+struct schemainfo_data {
+ DATA_BLOB ndr_blob;
+ struct dsdb_schema_info schi;
+ WERROR werr_expected;
+ bool test_both_ways;
+};
+
+/**
+ * Schema info test data in human-readable format (... kind of)
+ */
+static const struct {
+ const char *schema_info_str;
+ uint32_t revision;
+ const char *guid_str;
+ WERROR werr_expected;
+ bool test_both_ways;
+} _schemainfo_test_data[] = {
+ {
+ .schema_info_str = "FF0000000000000000000000000000000000000000",
+ .revision = 0,
+ .guid_str = "00000000-0000-0000-0000-000000000000",
+ .werr_expected = WERR_OK,
+ .test_both_ways = true
+ },
+ {
+ .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F",
+ .revision = 1,
+ .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
+ .werr_expected = WERR_OK,
+ .test_both_ways = true
+ },
+ {
+ .schema_info_str = "FFFFFFFFFFFD821C07C7455143A3DB51F75A630A7F",
+ .revision = 0xFFFFFFFF,
+ .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
+ .werr_expected = WERR_OK,
+ .test_both_ways = true
+ },
+ { /* len == 21 */
+ .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F00",
+ .revision = 1,
+ .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
+ .werr_expected = WERR_INVALID_PARAMETER,
+ .test_both_ways = false
+ },
+ { /* marker == FF */
+ .schema_info_str = "AA00000001FD821C07C7455143A3DB51F75A630A7F",
+ .revision = 1,
+ .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
+ .werr_expected = WERR_INVALID_PARAMETER,
+ .test_both_ways = false
+ }
+};
+
+/**
+ * Private data to be shared among all test in Test case
+ */
+struct drsut_schemainfo_data {
+ struct ldb_context *ldb;
+ struct ldb_module *ldb_module;
+ struct dsdb_schema *schema;
+
+ /* Initial schemaInfo set in ldb to test with */
+ struct dsdb_schema_info *schema_info;
+
+ uint32_t test_data_count;
+ struct schemainfo_data *test_data;
+};
+
+/**
+ * torture macro to assert for equal dsdb_schema_info's
+ */
+#define torture_assert_schema_info_equal(torture_ctx,got,expected,cmt)\
+ do { const struct dsdb_schema_info *__got = (got), *__expected = (expected); \
+ if (__got->revision != __expected->revision) { \
+ torture_result(torture_ctx, TORTURE_FAIL, \
+ __location__": "#got".revision %d did not match "#expected".revision %d: %s", \
+ (int)__got->revision, (int)__expected->revision, cmt); \
+ return false; \
+ } \
+ if (!GUID_equal(&__got->invocation_id, &__expected->invocation_id)) { \
+ torture_result(torture_ctx, TORTURE_FAIL, \
+ __location__": "#got".invocation_id did not match "#expected".invocation_id: %s", cmt); \
+ return false; \
+ } \
+ } while(0)
+
+/*
+ * forward declaration for internal functions
+ */
+static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
+ struct ldb_context *ldb,
+ const char *schema_info_str,
+ bool in_setup);
+
+
+/**
+ * Creates dsdb_schema_info object based on NDR data
+ * passed as hex string
+ */
+static bool _drsut_schemainfo_new(struct torture_context *tctx,
+ const char *schema_info_str, struct dsdb_schema_info **_si)
+{
+ WERROR werr;
+ DATA_BLOB blob;
+
+ blob = strhex_to_data_blob(tctx, schema_info_str);
+ if (!blob.data) {
+ torture_comment(tctx, "Not enough memory!\n");
+ return false;
+ }
+
+ werr = dsdb_schema_info_from_blob(&blob, tctx, _si);
+ if (!W_ERROR_IS_OK(werr)) {
+ torture_comment(tctx,
+ "Failed to create dsdb_schema_info object for %s: %s",
+ schema_info_str,
+ win_errstr(werr));
+ return false;
+ }
+
+ data_blob_free(&blob);
+
+ return true;
+}
+
+/**
+ * Creates dsdb_schema_info object based on predefined data
+ * Function is public as it is intended to be used by other
+ * tests (e.g. prefixMap tests)
+ */
+bool drsut_schemainfo_new(struct torture_context *tctx, struct dsdb_schema_info **_si)
+{
+ return _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, _si);
+}
+
+
+/*
+ * Tests dsdb_schema_info_new() and dsdb_schema_info_blob_new()
+ */
+static bool test_dsdb_schema_info_new(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ WERROR werr;
+ DATA_BLOB ndr_blob;
+ DATA_BLOB ndr_blob_expected;
+ struct dsdb_schema_info *schi;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(priv);
+ torture_assert(tctx, mem_ctx, "Not enough memory!");
+ ndr_blob_expected = strhex_to_data_blob(mem_ctx, SCHEMA_INFO_INIT_STR);
+ torture_assert(tctx, ndr_blob_expected.data, "Not enough memory!");
+
+ werr = dsdb_schema_info_new(mem_ctx, &schi);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_new() failed");
+ torture_assert_int_equal(tctx, schi->revision, 0,
+ "dsdb_schema_info_new() creates schemaInfo with invalid revision");
+ torture_assert(tctx, GUID_all_zero(&schi->invocation_id),
+ "dsdb_schema_info_new() creates schemaInfo with not ZERO GUID");
+
+ werr = dsdb_schema_info_blob_new(mem_ctx, &ndr_blob);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_blob_new() failed");
+ torture_assert_data_blob_equal(tctx, ndr_blob, ndr_blob_expected,
+ "dsdb_schema_info_blob_new() returned invalid blob");
+
+ talloc_free(mem_ctx);
+ return true;
+}
+
+/*
+ * Tests dsdb_schema_info_from_blob()
+ */
+static bool test_dsdb_schema_info_from_blob(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ uint32_t i;
+ WERROR werr;
+ char *msg;
+ struct dsdb_schema_info *schema_info;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(priv);
+ torture_assert(tctx, mem_ctx, "Not enough memory!");
+
+ for (i = 0; i < priv->test_data_count; i++) {
+ struct schemainfo_data *data = &priv->test_data[i];
+
+ msg = talloc_asprintf(tctx, "dsdb_schema_info_from_blob() [%d]-[%s]",
+ i, _schemainfo_test_data[i].schema_info_str);
+
+ werr = dsdb_schema_info_from_blob(&data->ndr_blob, mem_ctx, &schema_info);
+ torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
+
+ /* test returned data */
+ if (W_ERROR_IS_OK(werr)) {
+ torture_assert_schema_info_equal(tctx,
+ schema_info, &data->schi,
+ "after dsdb_schema_info_from_blob() call");
+ }
+ }
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
+/*
+ * Tests dsdb_blob_from_schema_info()
+ */
+static bool test_dsdb_blob_from_schema_info(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ uint32_t i;
+ WERROR werr;
+ char *msg;
+ DATA_BLOB ndr_blob;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(priv);
+ torture_assert(tctx, mem_ctx, "Not enough memory!");
+
+ for (i = 0; i < priv->test_data_count; i++) {
+ struct schemainfo_data *data = &priv->test_data[i];
+
+ /* not all test are valid reverse type of conversion */
+ if (!data->test_both_ways) {
+ continue;
+ }
+
+ msg = talloc_asprintf(tctx, "dsdb_blob_from_schema_info() [%d]-[%s]",
+ i, _schemainfo_test_data[i].schema_info_str);
+
+ werr = dsdb_blob_from_schema_info(&data->schi, mem_ctx, &ndr_blob);
+ torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
+
+ /* test returned data */
+ if (W_ERROR_IS_OK(werr)) {
+ torture_assert_data_blob_equal(tctx,
+ ndr_blob, data->ndr_blob,
+ "dsdb_blob_from_schema_info()");
+ }
+ }
+
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
+static bool test_dsdb_schema_info_cmp(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ DATA_BLOB blob;
+ struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
+ struct dsdb_schema_info schema_info;
+
+ ctr = talloc_zero(priv, struct drsuapi_DsReplicaOIDMapping_Ctr);
+ torture_assert(tctx, ctr, "Not enough memory!");
+
+ /* not enough elements */
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* an empty element for schemaInfo */
+ ctr->num_mappings = 1;
+ ctr->mappings = talloc_zero_array(ctr, struct drsuapi_DsReplicaOIDMapping, 1);
+ torture_assert(tctx, ctr->mappings, "Not enough memory!");
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with invalid schemaInfo - length != 21 */
+ blob = strhex_to_data_blob(ctr, "FF00000001FD821C07C7455143A3DB51F75A630A7F00");
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with invalid schemaInfo - marker != 0xFF */
+ blob = strhex_to_data_blob(ctr, "AA00000001FD821C07C7455143A3DB51F75A630A7F");
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but older one should be ok */
+ blob = strhex_to_data_blob(ctr, "FF0000000000000000000000000000000000000000");
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_OK,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with correct schemaInfo, but invalid ATTID */
+ schema_info = *priv->schema->schema_info;
+ torture_assert_werr_ok(tctx,
+ dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
+ "dsdb_blob_from_schema_info() failed");
+ ctr->mappings[0].id_prefix = 1;
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo */
+ ctr->mappings[0].id_prefix = 0;
+ torture_assert_werr_ok(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but older revision */
+ schema_info = *priv->schema->schema_info;
+ schema_info.revision -= 1;
+ torture_assert_werr_ok(tctx,
+ dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
+ "dsdb_blob_from_schema_info() failed");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_OK,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but newer revision */
+ schema_info = *priv->schema->schema_info;
+ schema_info.revision += 1;
+ torture_assert_werr_ok(tctx,
+ dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
+ "dsdb_blob_from_schema_info() failed");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_DS_DRA_SCHEMA_MISMATCH,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but newer revision and other invocationId */
+ schema_info = *priv->schema->schema_info;
+ schema_info.revision += 1;
+ schema_info.invocation_id.time_mid += 1;
+ torture_assert_werr_ok(tctx,
+ dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
+ "dsdb_blob_from_schema_info() failed");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_DS_DRA_SCHEMA_MISMATCH,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but older revision and other invocationId */
+ schema_info = *priv->schema->schema_info;
+ schema_info.revision -= 1;
+ schema_info.invocation_id.time_mid += 1;
+ torture_assert_werr_ok(tctx,
+ dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
+ "dsdb_blob_from_schema_info() failed");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_OK,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but same revision and other invocationId */
+ schema_info = *priv->schema->schema_info;
+ schema_info.invocation_id.time_mid += 1;
+ torture_assert_werr_ok(tctx,
+ dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
+ "dsdb_blob_from_schema_info() failed");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_DS_DRA_SCHEMA_CONFLICT,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ talloc_free(ctr);
+ return true;
+}
+
+/*
+ * Tests dsdb_module_schema_info_blob_read()
+ * and dsdb_module_schema_info_blob_write()
+ */
+static bool test_dsdb_module_schema_info_blob_rw(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ int ldb_err;
+ DATA_BLOB blob_write;
+ DATA_BLOB blob_read;
+
+ /* reset schmeInfo to know value */
+ torture_assert(tctx,
+ _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
+ "_drsut_ldb_schema_info_reset() failed");
+
+ /* write tests' default schemaInfo */
+ blob_write = strhex_to_data_blob(priv, SCHEMA_INFO_DEFAULT_STR);
+ torture_assert(tctx, blob_write.data, "Not enough memory!");
+
+ ldb_err = dsdb_module_schema_info_blob_write(priv->ldb_module,
+ DSDB_FLAG_TOP_MODULE,
+ &blob_write, NULL);
+ torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_write() failed");
+
+ ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
+ priv, &blob_read, NULL);
+ torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
+
+ /* check if we get what we wrote */
+ torture_assert_data_blob_equal(tctx, blob_read, blob_write,
+ "Write/Read of schemeInfo blob failed");
+
+ return true;
+}
+
+/*
+ * Tests dsdb_schema_update_schema_info()
+ */
+static bool test_dsdb_module_schema_info_update(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ int ldb_err;
+ WERROR werr;
+ DATA_BLOB blob;
+ struct dsdb_schema_info *schema_info;
+
+ /* reset schmeInfo to know value */
+ torture_assert(tctx,
+ _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
+ "_drsut_ldb_schema_info_reset() failed");
+
+ ldb_err = dsdb_module_schema_info_update(priv->ldb_module,
+ priv->schema,
+ DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM, NULL);
+ torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_update() failed");
+
+ /* get updated schemaInfo */
+ ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
+ priv, &blob, NULL);
+ torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
+
+ werr = dsdb_schema_info_from_blob(&blob, priv, &schema_info);
+ torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob() failed");
+
+ /* check against default schema_info */
+ torture_assert_schema_info_equal(tctx, schema_info, priv->schema_info,
+ "schemaInfo attribute no updated correctly");
+
+ return true;
+}
+
+
+/**
+ * Reset schemaInfo record to know value
+ */
+static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
+ struct ldb_context *ldb,
+ const char *schema_info_str,
+ bool in_setup)
+{
+ bool bret = true;
+ int ldb_err;
+ DATA_BLOB blob;
+ struct ldb_message *msg;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+
+ blob = strhex_to_data_blob(mem_ctx, schema_info_str);
+ torture_assert_goto(tctx, blob.data, bret, DONE, "Not enough memory!");
+
+ msg = ldb_msg_new(mem_ctx);
+ torture_assert_goto(tctx, msg, bret, DONE, "Not enough memory!");
+
+ msg->dn = ldb_get_schema_basedn(ldb);
+ ldb_err = ldb_msg_add_value(msg, "schemaInfo", &blob, NULL);
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
+ "ldb_msg_add_value() failed");
+
+ if (in_setup) {
+ ldb_err = ldb_add(ldb, msg);
+ } else {
+ ldb_err = dsdb_replace(ldb, msg, DSDB_MODIFY_PERMISSIVE);
+ }
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
+ "dsdb_replace() failed");
+
+DONE:
+ talloc_free(mem_ctx);
+ return bret;
+}
+
+/**
+ * Prepare temporary LDB and opens it
+ */
+static bool _drsut_ldb_setup(struct torture_context *tctx, struct drsut_schemainfo_data *priv)
+{
+ int ldb_err;
+ char *ldb_url;
+ bool bret = true;
+ char *tempdir = NULL;
+ NTSTATUS status;
+ TALLOC_CTX* mem_ctx;
+
+ mem_ctx = talloc_new(priv);
+ torture_assert(tctx, mem_ctx, "Not enough memory!");
+
+ status = torture_temp_dir(tctx, "drs_", &tempdir);
+ torture_assert_ntstatus_ok_goto(tctx, status, bret, DONE, "creating temp dir");
+
+ ldb_url = talloc_asprintf(priv, "%s/drs_schemainfo.ldb", tempdir);
+ torture_assert_goto(tctx, ldb_url, bret, DONE, "Not enough memory!");
+
+ /* create LDB */
+ priv->ldb = ldb_wrap_connect(priv, tctx->ev, tctx->lp_ctx,
+ ldb_url, NULL, NULL, 0);
+ torture_assert_goto(tctx, priv->ldb, bret, DONE, "ldb_wrap_connect() failed");
+
+ /* set some schemaNamingContext */
+ ldb_err = ldb_set_opaque(priv->ldb,
+ "schemaNamingContext",
+ ldb_dn_new(priv->ldb, priv->ldb, "CN=Schema,CN=Config"));
+ torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
+ "ldb_set_opaque() failed");
+
+ /* add schemaInfo attribute so tested layer could work properly */
+ torture_assert_goto(tctx,
+ _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, true),
+ bret, DONE,
+ "_drsut_ldb_schema_info_reset() failed");
+
+DONE:
+ talloc_free(tempdir);
+ talloc_free(mem_ctx);
+ return bret;
+}
+
+/*
+ * Setup/Teardown for test case
+ */
+static bool torture_drs_unit_schemainfo_setup(struct torture_context *tctx,
+ struct drsut_schemainfo_data **_priv)
+{
+ size_t i;
+ int ldb_err;
+ NTSTATUS status;
+ DATA_BLOB ndr_blob;
+ struct GUID guid;
+ struct drsut_schemainfo_data *priv;
+
+ priv = talloc_zero(tctx, struct drsut_schemainfo_data);
+ torture_assert(tctx, priv, "Not enough memory!");
+
+ /* returned allocated pointer here
+ * teardown() will be called even in case of failure,
+ * so we'll get a changes to clean up */
+ *_priv = priv;
+
+ /* create initial schemaInfo */
+ torture_assert(tctx,
+ _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema_info),
+ "Failed to create schema_info test object");
+
+ /* create data to test with */
+ priv->test_data_count = ARRAY_SIZE(_schemainfo_test_data);
+ priv->test_data = talloc_array(tctx, struct schemainfo_data, priv->test_data_count);
+
+ for (i = 0; i < ARRAY_SIZE(_schemainfo_test_data); i++) {
+ struct schemainfo_data *data = &priv->test_data[i];
+
+ ndr_blob = strhex_to_data_blob(priv,
+ _schemainfo_test_data[i].schema_info_str);
+ torture_assert(tctx, ndr_blob.data, "Not enough memory!");
+
+ status = GUID_from_string(_schemainfo_test_data[i].guid_str, &guid);
+ torture_assert_ntstatus_ok(tctx, status,
+ talloc_asprintf(tctx,
+ "GUID_from_string() failed for %s",
+ _schemainfo_test_data[i].guid_str));
+
+ data->ndr_blob = ndr_blob;
+ data->schi.invocation_id = guid;
+ data->schi.revision = _schemainfo_test_data[i].revision;
+ data->werr_expected = _schemainfo_test_data[i].werr_expected;
+ data->test_both_ways = _schemainfo_test_data[i].test_both_ways;
+
+ }
+
+ /* create temporary LDB and populate with data */
+ if (!_drsut_ldb_setup(tctx, priv)) {
+ return false;
+ }
+
+ /* create ldb_module mockup object */
+ priv->ldb_module = ldb_module_new(priv, priv->ldb, "schemaInfo_test_module", NULL);
+ torture_assert(tctx, priv->ldb_module, "Not enough memory!");
+
+ /* create schema mockup object */
+ priv->schema = dsdb_new_schema(priv);
+
+ /* set schema_info in dsdb_schema for testing */
+ torture_assert(tctx,
+ _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema->schema_info),
+ "Failed to create schema_info test object");
+
+ /* pre-cache invocationId for samdb_ntds_invocation_id()
+ * to work with our mock ldb */
+ ldb_err = ldb_set_opaque(priv->ldb, "cache.invocation_id",
+ &priv->schema_info->invocation_id);
+ torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "ldb_set_opaque() failed");
+
+ /* Perform all tests in transactions so that
+ * underlying modify calls not to fail */
+ ldb_err = ldb_transaction_start(priv->ldb);
+ torture_assert_int_equal(tctx,
+ ldb_err,
+ LDB_SUCCESS,
+ "ldb_transaction_start() failed");
+
+ return true;
+}
+
+static bool torture_drs_unit_schemainfo_teardown(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ int ldb_err;
+
+ /* commit pending transaction so we will
+ * be able to check what LDB state is */
+ ldb_err = ldb_transaction_commit(priv->ldb);
+ if (ldb_err != LDB_SUCCESS) {
+ torture_comment(tctx, "ldb_transaction_commit() - %s (%s)",
+ ldb_strerror(ldb_err),
+ ldb_errstring(priv->ldb));
+ }
+
+ talloc_free(priv);
+
+ return true;
+}
+
+/**
+ * Test case initialization for
+ * drs.unit.schemaInfo
+ */
+struct torture_tcase * torture_drs_unit_schemainfo(struct torture_suite *suite)
+{
+ typedef bool (*pfn_setup)(struct torture_context *, void **);
+ typedef bool (*pfn_teardown)(struct torture_context *, void *);
+ typedef bool (*pfn_run)(struct torture_context *, void *);
+
+ struct torture_tcase * tc = torture_suite_add_tcase(suite, "schemaInfo");
+
+ torture_tcase_set_fixture(tc,
+ (pfn_setup)torture_drs_unit_schemainfo_setup,
+ (pfn_teardown)torture_drs_unit_schemainfo_teardown);
+
+ tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::schemaInfo implementation");
+
+ torture_tcase_add_simple_test(tc, "dsdb_schema_info_new",
+ (pfn_run)test_dsdb_schema_info_new);
+ torture_tcase_add_simple_test(tc, "dsdb_schema_info_from_blob",
+ (pfn_run)test_dsdb_schema_info_from_blob);
+ torture_tcase_add_simple_test(tc, "dsdb_blob_from_schema_info",
+ (pfn_run)test_dsdb_blob_from_schema_info);
+ torture_tcase_add_simple_test(tc, "dsdb_schema_info_cmp",
+ (pfn_run)test_dsdb_schema_info_cmp);
+ torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_blob read|write",
+ (pfn_run)test_dsdb_module_schema_info_blob_rw);
+ torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_update",
+ (pfn_run)test_dsdb_module_schema_info_update);
+
+
+ return tc;
+}