s4:dsdb/schema: don't treat an older remote schema as SCHEMA_MISMATCH
[obnox/samba/samba-obnox.git] / source4 / torture / drs / unit / schemainfo_tests.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DRSUAPI schemaInfo unit tests
5
6    Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/filesys.h"
24 #include "torture/smbtorture.h"
25 #include "dsdb/samdb/samdb.h"
26 #include "dsdb/samdb/ldb_modules/util.h"
27 #include "ldb_wrap.h"
28 #include <ldb_module.h>
29 #include "torture/rpc/drsuapi.h"
30 #include "librpc/ndr/libndr.h"
31 #include "param/param.h"
32 #include "torture/drs/proto.h"
33 #include "torture/drs/proto.h"
34
35
36 /**
37  * schemaInfo to init ldb context with
38  *   Rev:  0
39  *   GUID: 00000000-0000-0000-0000-000000000000
40  */
41 #define SCHEMA_INFO_INIT_STR            "FF0000000000000000000000000000000000000000"
42
43 /**
44  * Default schema_info string to be used for testing
45  *   Rev:  01
46  *   GUID: 071c82fd-45c7-4351-a3db-51f75a630a7f
47  */
48 #define SCHEMA_INFO_DEFAULT_STR         "FF00000001FD821C07C7455143A3DB51F75A630A7F"
49
50 /**
51  * Schema info data to test with
52  */
53 struct schemainfo_data {
54         DATA_BLOB       ndr_blob;
55         struct dsdb_schema_info schi;
56         WERROR          werr_expected;
57         bool            test_both_ways;
58 };
59
60 /**
61  * Schema info test data in human-readable format (... kind of)
62  */
63 static const struct {
64         const char      *schema_info_str;
65         uint32_t        revision;
66         const char      *guid_str;
67         WERROR          werr_expected;
68         bool            test_both_ways;
69 } _schemainfo_test_data[] = {
70         {
71                 .schema_info_str = "FF0000000000000000000000000000000000000000",
72                 .revision = 0,
73                 .guid_str = "00000000-0000-0000-0000-000000000000",
74                 .werr_expected = WERR_OK,
75                 .test_both_ways = true
76         },
77         {
78                 .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F",
79                 .revision = 1,
80                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
81                 .werr_expected = WERR_OK,
82                 .test_both_ways = true
83         },
84         {
85                 .schema_info_str = "FFFFFFFFFFFD821C07C7455143A3DB51F75A630A7F",
86                 .revision = 0xFFFFFFFF,
87                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
88                 .werr_expected = WERR_OK,
89                 .test_both_ways = true
90         },
91         { /* len == 21 */
92                 .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F00",
93                 .revision = 1,
94                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
95                 .werr_expected = WERR_INVALID_PARAMETER,
96                 .test_both_ways = false
97         },
98         { /* marker == FF */
99                 .schema_info_str = "AA00000001FD821C07C7455143A3DB51F75A630A7F",
100                 .revision = 1,
101                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
102                 .werr_expected = WERR_INVALID_PARAMETER,
103                 .test_both_ways = false
104         }
105 };
106
107 /**
108  * Private data to be shared among all test in Test case
109  */
110 struct drsut_schemainfo_data {
111         struct ldb_context *ldb;
112         struct ldb_module  *ldb_module;
113         struct dsdb_schema *schema;
114
115         /* Initial schemaInfo set in ldb to test with */
116         struct dsdb_schema_info *schema_info;
117
118         uint32_t test_data_count;
119         struct schemainfo_data *test_data;
120 };
121
122 /**
123  * torture macro to assert for equal dsdb_schema_info's
124  */
125 #define torture_assert_schema_info_equal(torture_ctx,got,expected,cmt)\
126         do { const struct dsdb_schema_info *__got = (got), *__expected = (expected); \
127         if (__got->revision != __expected->revision) { \
128                 torture_result(torture_ctx, TORTURE_FAIL, \
129                                __location__": "#got".revision %d did not match "#expected".revision %d: %s", \
130                                (int)__got->revision, (int)__expected->revision, cmt); \
131                 return false; \
132         } \
133         if (!GUID_equal(&__got->invocation_id, &__expected->invocation_id)) { \
134                 torture_result(torture_ctx, TORTURE_FAIL, \
135                                __location__": "#got".invocation_id did not match "#expected".invocation_id: %s", cmt); \
136                 return false; \
137         } \
138         } while(0)
139
140 /*
141  * forward declaration for internal functions
142  */
143 static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
144                                          struct ldb_context *ldb,
145                                          const char *schema_info_str,
146                                          bool in_setup);
147
148
149 /**
150  * Creates dsdb_schema_info object based on NDR data
151  * passed as hex string
152  */
153 static bool _drsut_schemainfo_new(struct torture_context *tctx,
154                                   const char *schema_info_str, struct dsdb_schema_info **_si)
155 {
156         WERROR werr;
157         DATA_BLOB blob;
158
159         blob = strhex_to_data_blob(tctx, schema_info_str);
160         if (!blob.data) {
161                 torture_comment(tctx, "Not enough memory!\n");
162                 return false;
163         }
164
165         werr = dsdb_schema_info_from_blob(&blob, tctx, _si);
166         if (!W_ERROR_IS_OK(werr)) {
167                 torture_comment(tctx,
168                                 "Failed to create dsdb_schema_info object for %s: %s",
169                                 schema_info_str,
170                                 win_errstr(werr));
171                 return false;
172         }
173
174         data_blob_free(&blob);
175
176         return true;
177 }
178
179 /**
180  * Creates dsdb_schema_info object based on predefined data
181  * Function is public as it is intended to be used by other
182  * tests (e.g. prefixMap tests)
183  */
184 bool drsut_schemainfo_new(struct torture_context *tctx, struct dsdb_schema_info **_si)
185 {
186         return _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, _si);
187 }
188
189
190 /*
191  * Tests dsdb_schema_info_new() and dsdb_schema_info_blob_new()
192  */
193 static bool test_dsdb_schema_info_new(struct torture_context *tctx,
194                                       struct drsut_schemainfo_data *priv)
195 {
196         WERROR werr;
197         DATA_BLOB ndr_blob;
198         DATA_BLOB ndr_blob_expected;
199         struct dsdb_schema_info *schi;
200         TALLOC_CTX *mem_ctx;
201
202         mem_ctx = talloc_new(priv);
203         torture_assert(tctx, mem_ctx, "Not enough memory!");
204         ndr_blob_expected = strhex_to_data_blob(mem_ctx, SCHEMA_INFO_INIT_STR);
205         torture_assert(tctx, ndr_blob_expected.data, "Not enough memory!");
206
207         werr = dsdb_schema_info_new(mem_ctx, &schi);
208         torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_new() failed");
209         torture_assert_int_equal(tctx, schi->revision, 0,
210                                  "dsdb_schema_info_new() creates schemaInfo with invalid revision");
211         torture_assert(tctx, GUID_all_zero(&schi->invocation_id),
212                         "dsdb_schema_info_new() creates schemaInfo with not ZERO GUID");
213
214         werr = dsdb_schema_info_blob_new(mem_ctx, &ndr_blob);
215         torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_blob_new() failed");
216         torture_assert_data_blob_equal(tctx, ndr_blob, ndr_blob_expected,
217                                        "dsdb_schema_info_blob_new() returned invalid blob");
218
219         talloc_free(mem_ctx);
220         return true;
221 }
222
223 /*
224  * Tests dsdb_schema_info_from_blob()
225  */
226 static bool test_dsdb_schema_info_from_blob(struct torture_context *tctx,
227                                             struct drsut_schemainfo_data *priv)
228 {
229         int i;
230         WERROR werr;
231         char *msg;
232         struct dsdb_schema_info *schema_info;
233         TALLOC_CTX *mem_ctx;
234
235         mem_ctx = talloc_new(priv);
236         torture_assert(tctx, mem_ctx, "Not enough memory!");
237
238         for (i = 0; i < priv->test_data_count; i++) {
239                 struct schemainfo_data *data = &priv->test_data[i];
240
241                 msg = talloc_asprintf(tctx, "dsdb_schema_info_from_blob() [%d]-[%s]",
242                                       i, _schemainfo_test_data[i].schema_info_str);
243
244                 werr = dsdb_schema_info_from_blob(&data->ndr_blob, mem_ctx, &schema_info);
245                 torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
246
247                 /* test returned data */
248                 if (W_ERROR_IS_OK(werr)) {
249                         torture_assert_schema_info_equal(tctx,
250                                                          schema_info, &data->schi,
251                                                          "after dsdb_schema_info_from_blob() call");
252                 }
253         }
254
255         talloc_free(mem_ctx);
256
257         return true;
258 }
259
260 /*
261  * Tests dsdb_blob_from_schema_info()
262  */
263 static bool test_dsdb_blob_from_schema_info(struct torture_context *tctx,
264                                             struct drsut_schemainfo_data *priv)
265 {
266         int i;
267         WERROR werr;
268         char *msg;
269         DATA_BLOB ndr_blob;
270         TALLOC_CTX *mem_ctx;
271
272         mem_ctx = talloc_new(priv);
273         torture_assert(tctx, mem_ctx, "Not enough memory!");
274
275         for (i = 0; i < priv->test_data_count; i++) {
276                 struct schemainfo_data *data = &priv->test_data[i];
277
278                 /* not all test are valid reverse type of conversion */
279                 if (!data->test_both_ways) {
280                         continue;
281                 }
282
283                 msg = talloc_asprintf(tctx, "dsdb_blob_from_schema_info() [%d]-[%s]",
284                                       i, _schemainfo_test_data[i].schema_info_str);
285
286                 werr = dsdb_blob_from_schema_info(&data->schi, mem_ctx, &ndr_blob);
287                 torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
288
289                 /* test returned data */
290                 if (W_ERROR_IS_OK(werr)) {
291                         torture_assert_data_blob_equal(tctx,
292                                                        ndr_blob, data->ndr_blob,
293                                                        "dsdb_blob_from_schema_info()");
294                 }
295         }
296
297         talloc_free(mem_ctx);
298
299         return true;
300 }
301
302 static bool test_dsdb_schema_info_cmp(struct torture_context *tctx,
303                                       struct drsut_schemainfo_data *priv)
304 {
305         DATA_BLOB blob;
306         struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
307         struct dsdb_schema_info schema_info;
308
309         ctr = talloc_zero(priv, struct drsuapi_DsReplicaOIDMapping_Ctr);
310         torture_assert(tctx, ctr, "Not enough memory!");
311
312         /* not enough elements */
313         torture_assert_werr_equal(tctx,
314                                   dsdb_schema_info_cmp(priv->schema, ctr),
315                                   WERR_INVALID_PARAMETER,
316                                   "dsdb_schema_info_cmp(): unexpected result");
317
318         /* an empty element for schemaInfo */
319         ctr->num_mappings = 1;
320         ctr->mappings = talloc_zero_array(ctr, struct drsuapi_DsReplicaOIDMapping, 1);
321         torture_assert(tctx, ctr->mappings, "Not enough memory!");
322         torture_assert_werr_equal(tctx,
323                                   dsdb_schema_info_cmp(priv->schema, ctr),
324                                   WERR_INVALID_PARAMETER,
325                                   "dsdb_schema_info_cmp(): unexpected result");
326
327         /* test with invalid schemaInfo - length != 21 */
328         blob = strhex_to_data_blob(ctr, "FF00000001FD821C07C7455143A3DB51F75A630A7F00");
329         torture_assert(tctx, blob.data, "Not enough memory!");
330         ctr->mappings[0].oid.length     = blob.length;
331         ctr->mappings[0].oid.binary_oid = blob.data;
332         torture_assert_werr_equal(tctx,
333                                   dsdb_schema_info_cmp(priv->schema, ctr),
334                                   WERR_INVALID_PARAMETER,
335                                   "dsdb_schema_info_cmp(): unexpected result");
336
337         /* test with invalid schemaInfo - marker != 0xFF */
338         blob = strhex_to_data_blob(ctr, "AA00000001FD821C07C7455143A3DB51F75A630A7F");
339         torture_assert(tctx, blob.data, "Not enough memory!");
340         ctr->mappings[0].oid.length     = blob.length;
341         ctr->mappings[0].oid.binary_oid = blob.data;
342         torture_assert_werr_equal(tctx,
343                                   dsdb_schema_info_cmp(priv->schema, ctr),
344                                   WERR_INVALID_PARAMETER,
345                                   "dsdb_schema_info_cmp(): unexpected result");
346
347         /* test with valid schemaInfo, but older one should be ok */
348         blob = strhex_to_data_blob(ctr, "FF0000000000000000000000000000000000000000");
349         torture_assert(tctx, blob.data, "Not enough memory!");
350         ctr->mappings[0].oid.length     = blob.length;
351         ctr->mappings[0].oid.binary_oid = blob.data;
352         torture_assert_werr_equal(tctx,
353                                   dsdb_schema_info_cmp(priv->schema, ctr),
354                                   WERR_OK,
355                                   "dsdb_schema_info_cmp(): unexpected result");
356
357         /* test with correct schemaInfo, but invalid ATTID */
358         schema_info = *priv->schema->schema_info;
359         torture_assert_werr_ok(tctx,
360                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
361                 "dsdb_blob_from_schema_info() failed");
362         ctr->mappings[0].id_prefix      = 1;
363         ctr->mappings[0].oid.length     = blob.length;
364         ctr->mappings[0].oid.binary_oid = blob.data;
365         torture_assert_werr_equal(tctx,
366                                   dsdb_schema_info_cmp(priv->schema, ctr),
367                                   WERR_INVALID_PARAMETER,
368                                   "dsdb_schema_info_cmp(): unexpected result");
369
370         /* test with valid schemaInfo */
371         ctr->mappings[0].id_prefix      = 0;
372         torture_assert_werr_ok(tctx,
373                                dsdb_schema_info_cmp(priv->schema, ctr),
374                                "dsdb_schema_info_cmp(): unexpected result");
375
376         /* test with valid schemaInfo, but older revision */
377         schema_info = *priv->schema->schema_info;
378         schema_info.revision -= 1;
379         torture_assert_werr_ok(tctx,
380                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
381                 "dsdb_blob_from_schema_info() failed");
382         ctr->mappings[0].oid.length     = blob.length;
383         ctr->mappings[0].oid.binary_oid = blob.data;
384         torture_assert_werr_equal(tctx,
385                                   dsdb_schema_info_cmp(priv->schema, ctr),
386                                   WERR_OK,
387                                   "dsdb_schema_info_cmp(): unexpected result");
388
389         /* test with valid schemaInfo, but newer revision */
390         schema_info = *priv->schema->schema_info;
391         schema_info.revision += 1;
392         torture_assert_werr_ok(tctx,
393                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
394                 "dsdb_blob_from_schema_info() failed");
395         ctr->mappings[0].oid.length     = blob.length;
396         ctr->mappings[0].oid.binary_oid = blob.data;
397         torture_assert_werr_equal(tctx,
398                                   dsdb_schema_info_cmp(priv->schema, ctr),
399                                   WERR_DS_DRA_SCHEMA_MISMATCH,
400                                   "dsdb_schema_info_cmp(): unexpected result");
401
402         /* test with valid schemaInfo, but newer revision and other invocationId */
403         schema_info = *priv->schema->schema_info;
404         schema_info.revision += 1;
405         schema_info.invocation_id.time_mid += 1;
406         torture_assert_werr_ok(tctx,
407                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
408                 "dsdb_blob_from_schema_info() failed");
409         ctr->mappings[0].oid.length     = blob.length;
410         ctr->mappings[0].oid.binary_oid = blob.data;
411         torture_assert_werr_equal(tctx,
412                                   dsdb_schema_info_cmp(priv->schema, ctr),
413                                   WERR_DS_DRA_SCHEMA_MISMATCH,
414                                   "dsdb_schema_info_cmp(): unexpected result");
415
416         /* test with valid schemaInfo, but older revision and other invocationId */
417         schema_info = *priv->schema->schema_info;
418         schema_info.revision -= 1;
419         schema_info.invocation_id.time_mid += 1;
420         torture_assert_werr_ok(tctx,
421                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
422                 "dsdb_blob_from_schema_info() failed");
423         ctr->mappings[0].oid.length     = blob.length;
424         ctr->mappings[0].oid.binary_oid = blob.data;
425         torture_assert_werr_equal(tctx,
426                                   dsdb_schema_info_cmp(priv->schema, ctr),
427                                   WERR_OK,
428                                   "dsdb_schema_info_cmp(): unexpected result");
429
430         /* test with valid schemaInfo, but same revision and other invocationId */
431         schema_info = *priv->schema->schema_info;
432         schema_info.invocation_id.time_mid += 1;
433         torture_assert_werr_ok(tctx,
434                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
435                 "dsdb_blob_from_schema_info() failed");
436         ctr->mappings[0].oid.length     = blob.length;
437         ctr->mappings[0].oid.binary_oid = blob.data;
438         torture_assert_werr_equal(tctx,
439                                   dsdb_schema_info_cmp(priv->schema, ctr),
440                                   WERR_DS_DRA_SCHEMA_CONFLICT,
441                                   "dsdb_schema_info_cmp(): unexpected result");
442
443         talloc_free(ctr);
444         return true;
445 }
446
447 /*
448  * Tests dsdb_module_schema_info_blob_read()
449  *   and dsdb_module_schema_info_blob_write()
450  */
451 static bool test_dsdb_module_schema_info_blob_rw(struct torture_context *tctx,
452                                                 struct drsut_schemainfo_data *priv)
453 {
454         int ldb_err;
455         DATA_BLOB blob_write;
456         DATA_BLOB blob_read;
457
458         /* reset schmeInfo to know value */
459         torture_assert(tctx,
460                        _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
461                        "_drsut_ldb_schema_info_reset() failed");
462
463         /* write tests' default schemaInfo */
464         blob_write = strhex_to_data_blob(priv, SCHEMA_INFO_DEFAULT_STR);
465         torture_assert(tctx, blob_write.data, "Not enough memory!");
466
467         ldb_err = dsdb_module_schema_info_blob_write(priv->ldb_module,
468                                                      DSDB_FLAG_TOP_MODULE,
469                                                      &blob_write, NULL);
470         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_write() failed");
471
472         ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
473                                                     priv, &blob_read, NULL);
474         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
475
476         /* check if we get what we wrote */
477         torture_assert_data_blob_equal(tctx, blob_read, blob_write,
478                                        "Write/Read of schemeInfo blob failed");
479
480         return true;
481 }
482
483 /*
484  * Tests dsdb_schema_update_schema_info()
485  */
486 static bool test_dsdb_module_schema_info_update(struct torture_context *tctx,
487                                                 struct drsut_schemainfo_data *priv)
488 {
489         int ldb_err;
490         WERROR werr;
491         DATA_BLOB blob;
492         struct dsdb_schema_info *schema_info;
493
494         /* reset schmeInfo to know value */
495         torture_assert(tctx,
496                        _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
497                        "_drsut_ldb_schema_info_reset() failed");
498
499         ldb_err = dsdb_module_schema_info_update(priv->ldb_module,
500                                                  priv->schema,
501                                                  DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM, NULL);
502         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_update() failed");
503
504         /* get updated schemaInfo */
505         ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
506                                                     priv, &blob, NULL);
507         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
508
509         werr = dsdb_schema_info_from_blob(&blob, priv, &schema_info);
510         torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob() failed");
511
512         /* check against default schema_info */
513         torture_assert_schema_info_equal(tctx, schema_info, priv->schema_info,
514                                           "schemaInfo attribute no updated correctly");
515
516         return true;
517 }
518
519
520 /**
521  * Reset schemaInfo record to know value
522  */
523 static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
524                                          struct ldb_context *ldb,
525                                          const char *schema_info_str,
526                                          bool in_setup)
527 {
528         bool bret = true;
529         int ldb_err;
530         DATA_BLOB blob;
531         struct ldb_message *msg;
532         TALLOC_CTX *mem_ctx = talloc_new(tctx);
533
534         blob = strhex_to_data_blob(mem_ctx, schema_info_str);
535         torture_assert_goto(tctx, blob.data, bret, DONE, "Not enough memory!");
536
537         msg = ldb_msg_new(mem_ctx);
538         torture_assert_goto(tctx, msg, bret, DONE, "Not enough memory!");
539
540         msg->dn = ldb_get_schema_basedn(ldb);
541         ldb_err = ldb_msg_add_value(msg, "schemaInfo", &blob, NULL);
542         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
543                                       "ldb_msg_add_value() failed");
544
545         if (in_setup) {
546                 ldb_err = ldb_add(ldb, msg);
547         } else {
548                 ldb_err = dsdb_replace(ldb, msg, DSDB_MODIFY_PERMISSIVE);
549         }
550         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
551                                       "dsdb_replace() failed");
552
553 DONE:
554         talloc_free(mem_ctx);
555         return bret;
556 }
557
558 /**
559  * Prepare temporary LDB and opens it
560  */
561 static bool _drsut_ldb_setup(struct torture_context *tctx, struct drsut_schemainfo_data *priv)
562 {
563         int ldb_err;
564         char *ldb_url;
565         bool bret = true;
566         char *tempdir = NULL;
567         NTSTATUS status;
568         TALLOC_CTX* mem_ctx;
569
570         mem_ctx = talloc_new(priv);
571         torture_assert(tctx, mem_ctx, "Not enough memory!");
572
573         status = torture_temp_dir(tctx, "drs_", &tempdir);
574         torture_assert_ntstatus_ok_goto(tctx, status, bret, DONE, "creating temp dir");
575
576         ldb_url = talloc_asprintf(priv, "%s/drs_schemainfo.ldb", tempdir);
577         torture_assert_goto(tctx, ldb_url, bret, DONE, "Not enough memory!");
578
579         /* create LDB */
580         priv->ldb = ldb_wrap_connect(priv, tctx->ev, tctx->lp_ctx,
581                                      ldb_url, NULL, NULL, 0);
582         torture_assert_goto(tctx, priv->ldb, bret, DONE,  "ldb_wrap_connect() failed");
583
584         /* set some schemaNamingContext */
585         ldb_err = ldb_set_opaque(priv->ldb,
586                                  "schemaNamingContext",
587                                  ldb_dn_new(priv->ldb, priv->ldb, "CN=Schema,CN=Config"));
588         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
589                                       "ldb_set_opaque() failed");
590
591         /* add schemaInfo attribute so tested layer could work properly */
592         torture_assert_goto(tctx,
593                             _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, true),
594                             bret, DONE,
595                             "_drsut_ldb_schema_info_reset() failed");
596
597 DONE:
598         talloc_free(tempdir);
599         talloc_free(mem_ctx);
600         return bret;
601 }
602
603 /*
604  * Setup/Teardown for test case
605  */
606 static bool torture_drs_unit_schemainfo_setup(struct torture_context *tctx,
607                                               struct drsut_schemainfo_data **_priv)
608 {
609         int i;
610         int ldb_err;
611         NTSTATUS status;
612         DATA_BLOB ndr_blob;
613         struct GUID guid;
614         struct drsut_schemainfo_data *priv;
615
616         priv = talloc_zero(tctx, struct drsut_schemainfo_data);
617         torture_assert(tctx, priv, "Not enough memory!");
618
619         /* returned allocated pointer here
620          * teardown() will be called even in case of failure,
621          * so we'll get a changes to clean up  */
622         *_priv = priv;
623
624         /* create initial schemaInfo */
625         torture_assert(tctx,
626                        _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema_info),
627                        "Failed to create schema_info test object");
628
629         /* create data to test with */
630         priv->test_data_count = ARRAY_SIZE(_schemainfo_test_data);
631         priv->test_data = talloc_array(tctx, struct schemainfo_data, priv->test_data_count);
632
633         for (i = 0; i < ARRAY_SIZE(_schemainfo_test_data); i++) {
634                 struct schemainfo_data *data = &priv->test_data[i];
635
636                 ndr_blob = strhex_to_data_blob(priv,
637                                                _schemainfo_test_data[i].schema_info_str);
638                 torture_assert(tctx, ndr_blob.data, "Not enough memory!");
639
640                 status = GUID_from_string(_schemainfo_test_data[i].guid_str, &guid);
641                 torture_assert_ntstatus_ok(tctx, status,
642                                            talloc_asprintf(tctx,
643                                                            "GUID_from_string() failed for %s",
644                                                            _schemainfo_test_data[i].guid_str));
645
646                 data->ndr_blob           = ndr_blob;
647                 data->schi.invocation_id = guid;
648                 data->schi.revision      = _schemainfo_test_data[i].revision;
649                 data->werr_expected      = _schemainfo_test_data[i].werr_expected;
650                 data->test_both_ways     = _schemainfo_test_data[i].test_both_ways;
651
652         }
653
654         /* create temporary LDB and populate with data */
655         if (!_drsut_ldb_setup(tctx, priv)) {
656                 return false;
657         }
658
659         /* create ldb_module mockup object */
660         priv->ldb_module = ldb_module_new(priv, priv->ldb, "schemaInfo_test_module", NULL);
661         torture_assert(tctx, priv->ldb_module, "Not enough memory!");
662
663         /* create schema mockup object */
664         priv->schema = dsdb_new_schema(priv);
665
666         /* set schema_info in dsdb_schema for testing */
667         torture_assert(tctx,
668                        _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema->schema_info),
669                        "Failed to create schema_info test object");
670
671         /* pre-cache invocationId for samdb_ntds_invocation_id()
672          * to work with our mock ldb */
673         ldb_err = ldb_set_opaque(priv->ldb, "cache.invocation_id",
674                                  &priv->schema_info->invocation_id);
675         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "ldb_set_opaque() failed");
676
677         /* Perform all tests in transactions so that
678          * underlying modify calls not to fail */
679         ldb_err = ldb_transaction_start(priv->ldb);
680         torture_assert_int_equal(tctx,
681                                  ldb_err,
682                                  LDB_SUCCESS,
683                                  "ldb_transaction_start() failed");
684
685         return true;
686 }
687
688 static bool torture_drs_unit_schemainfo_teardown(struct torture_context *tctx,
689                                                  struct drsut_schemainfo_data *priv)
690 {
691         int ldb_err;
692
693         /* commit pending transaction so we will
694          * be able to check what LDB state is */
695         ldb_err = ldb_transaction_commit(priv->ldb);
696         if (ldb_err != LDB_SUCCESS) {
697                 torture_comment(tctx, "ldb_transaction_commit() - %s (%s)",
698                                 ldb_strerror(ldb_err),
699                                 ldb_errstring(priv->ldb));
700         }
701
702         talloc_free(priv);
703
704         return true;
705 }
706
707 /**
708  * Test case initialization for
709  * drs.unit.schemaInfo
710  */
711 struct torture_tcase * torture_drs_unit_schemainfo(struct torture_suite *suite)
712 {
713         typedef bool (*pfn_setup)(struct torture_context *, void **);
714         typedef bool (*pfn_teardown)(struct torture_context *, void *);
715         typedef bool (*pfn_run)(struct torture_context *, void *);
716
717         struct torture_tcase * tc = torture_suite_add_tcase(suite, "schemaInfo");
718
719         torture_tcase_set_fixture(tc,
720                                   (pfn_setup)torture_drs_unit_schemainfo_setup,
721                                   (pfn_teardown)torture_drs_unit_schemainfo_teardown);
722
723         tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::schemaInfo implementation");
724
725         torture_tcase_add_simple_test(tc, "dsdb_schema_info_new",
726                                       (pfn_run)test_dsdb_schema_info_new);
727         torture_tcase_add_simple_test(tc, "dsdb_schema_info_from_blob",
728                                       (pfn_run)test_dsdb_schema_info_from_blob);
729         torture_tcase_add_simple_test(tc, "dsdb_blob_from_schema_info",
730                                       (pfn_run)test_dsdb_blob_from_schema_info);
731         torture_tcase_add_simple_test(tc, "dsdb_schema_info_cmp",
732                                       (pfn_run)test_dsdb_schema_info_cmp);
733         torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_blob read|write",
734                                       (pfn_run)test_dsdb_module_schema_info_blob_rw);
735         torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_update",
736                                       (pfn_run)test_dsdb_module_schema_info_update);
737
738
739         return tc;
740 }