[SCM] Samba Shared Repository - branch master updated

Jelmer Vernooij jelmer at samba.org
Sun Sep 19 13:35:03 MDT 2010


The branch, master has been updated
       via  dfedbae testtools: Import newer upstream revision.
       via  1fc1be4 Fix regf.idl, subkey and rootkey types were switched.
       via  7efcb3c Fix file corruption (non-updated header) on new allocation.
       via  d0cef92 Fix crash when no subkeys exist. Fix writing outside of buffer error by regf backend.
       via  2c3f560 Add python bindings for open_hive function to be able to load REGF files.
      from  5d80710 s4/fsmo: Naming master support added

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit dfedbaeb055acb0d7abf74b9534308149a018ee4
Author: Jelmer Vernooij <jelmer at samba.org>
Date:   Sun Sep 19 12:29:42 2010 -0700

    testtools: Import newer upstream revision.
    
    This fixes (among other things) a warning during 'make test' on systems with Python 2.6.

commit 1fc1be4685667f95e855fd2f781651c341e06fbd
Author: wilco at baanhofman.nl <wilco at baanhofman.nl>
Date:   Mon Aug 30 12:17:41 2010 +0200

    Fix regf.idl, subkey and rootkey types were switched.
    
    Signed-off-by: Jelmer Vernooij <jelmer at samba.org>

commit 7efcb3ca66b12972de3707164c7bd415619a4bb8
Author: wilco at baanhofman.nl <wilco at baanhofman.nl>
Date:   Mon Jul 26 23:00:43 2010 +0200

    Fix file corruption (non-updated header) on new allocation.
    
    Also fixes debug messages to use hex offsets.
    
    Signed-off-by: Jelmer Vernooij <jelmer at samba.org>

commit d0cef92532f7c943e1c70d49ed96f090235b928e
Author: wilco at baanhofman.nl <wilco at baanhofman.nl>
Date:   Mon Jul 26 20:13:22 2010 +0200

    Fix crash when no subkeys exist. Fix writing outside of buffer error by regf backend.
    
    Signed-off-by: Jelmer Vernooij <jelmer at samba.org>

commit 2c3f56098b0322db2e74e860a0f236fde9f74bbc
Author: wilco at baanhofman.nl <wilco at baanhofman.nl>
Date:   Mon Jul 26 12:32:32 2010 +0200

    Add python bindings for open_hive function to be able to load REGF files.
    
    Signed-off-by: Jelmer Vernooij <jelmer at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/testtools/NEWS                              |   45 +++++++++++++---------
 lib/testtools/testtools/matchers.py             |    9 ++++
 lib/testtools/testtools/testcase.py             |   29 +++++++-------
 lib/testtools/testtools/tests/test_testtools.py |   32 +++++++++++++--
 source4/lib/registry/pyregistry.c               |   47 +++++++++++++++++++++--
 source4/lib/registry/regf.c                     |   40 ++++++++++++++-----
 source4/lib/registry/regf.idl                   |    4 +-
 7 files changed, 153 insertions(+), 53 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/testtools/NEWS b/lib/testtools/NEWS
index dc5e6df..596df0d 100644
--- a/lib/testtools/NEWS
+++ b/lib/testtools/NEWS
@@ -4,6 +4,15 @@ testtools NEWS
 NEXT
 ~~~~
 
+Improvements
+------------
+
+* Code duplication between assertEqual and the matcher Equals has been removed.
+
+* In normal circumstances, a TestCase will no longer share details with clones
+  of itself. (Andrew Bennetts, bug #637725)
+
+
 0.9.6
 ~~~~~
 
@@ -17,32 +26,32 @@ patches and TestCase.assertEqual gives slightly nicer errors.
 Improvements
 ------------
 
- * 'TestCase.assertEqual' now formats errors a little more nicely, in the
-   style of bzrlib.
+* 'TestCase.assertEqual' now formats errors a little more nicely, in the
+  style of bzrlib.
 
- * Added `PlaceHolder` and `ErrorHolder`, TestCase-like objects that can be
-   used to add results to a `TestResult`.
+* Added `PlaceHolder` and `ErrorHolder`, TestCase-like objects that can be
+  used to add results to a `TestResult`.
 
- * 'Mismatch' now takes optional description and details parameters, so
-   custom Matchers aren't compelled to make their own subclass.
+* 'Mismatch' now takes optional description and details parameters, so
+  custom Matchers aren't compelled to make their own subclass.
 
- * jml added a built-in UTF8_TEXT ContentType to make it slightly easier to
-   add details to test results. See bug #520044.
+* jml added a built-in UTF8_TEXT ContentType to make it slightly easier to
+  add details to test results. See bug #520044.
 
- * Fix a bug in our built-in matchers where assertThat would blow up if any
-   of them failed. All built-in mismatch objects now provide get_details().
+* Fix a bug in our built-in matchers where assertThat would blow up if any
+  of them failed. All built-in mismatch objects now provide get_details().
 
- * New 'Is' matcher, which lets you assert that a thing is identical to
-   another thing.
+* New 'Is' matcher, which lets you assert that a thing is identical to
+  another thing.
 
- * New 'LessThan' matcher which lets you assert that a thing is less than
-   another thing.
+* New 'LessThan' matcher which lets you assert that a thing is less than
+  another thing.
 
- * TestCase now has a 'patch()' method to make it easier to monkey-patching
-   objects in tests. See the manual for more information. Fixes bug #310770.
+* TestCase now has a 'patch()' method to make it easier to monkey-patching
+  objects in tests. See the manual for more information. Fixes bug #310770.
 
- * MultiTestResult methods now pass back return values from the results it
-   forwards to.
+* MultiTestResult methods now pass back return values from the results it
+  forwards to.
 
 0.9.5
 ~~~~~
diff --git a/lib/testtools/testtools/matchers.py b/lib/testtools/testtools/matchers.py
index 6a4c82a..61b5bd7 100644
--- a/lib/testtools/testtools/matchers.py
+++ b/lib/testtools/testtools/matchers.py
@@ -25,6 +25,7 @@ __all__ = [
 
 import doctest
 import operator
+from pprint import pformat
 
 
 class Matcher(object):
@@ -178,6 +179,14 @@ class _BinaryMismatch(Mismatch):
         self.other = other
 
     def describe(self):
+        left = repr(self.expected)
+        right = repr(self.other)
+        if len(left) + len(right) > 70:
+            return "%s:\nreference = %s\nactual = %s\n" % (
+                self._mismatch_string, pformat(self.expected),
+                pformat(self.other))
+        else:
+            return "%s %s %s" % (left, self._mismatch_string,right)
         return "%r %s %r" % (self.expected, self._mismatch_string, self.other)
 
 
diff --git a/lib/testtools/testtools/testcase.py b/lib/testtools/testtools/testcase.py
index 48eec71..959c129 100644
--- a/lib/testtools/testtools/testcase.py
+++ b/lib/testtools/testtools/testcase.py
@@ -17,13 +17,16 @@ try:
 except ImportError:
     wraps = None
 import itertools
-from pprint import pformat
 import sys
 import types
 import unittest
 
 from testtools import content
 from testtools.compat import advance_iterator
+from testtools.matchers import (
+    Annotate,
+    Equals,
+    )
 from testtools.monkey import patch
 from testtools.runtest import RunTest
 from testtools.testresult import TestResult
@@ -81,7 +84,9 @@ class TestCase(unittest.TestCase):
         self._traceback_id_gen = itertools.count(0)
         self.__setup_called = False
         self.__teardown_called = False
-        self.__details = {}
+        # __details is lazy-initialized so that a constructed-but-not-run
+        # TestCase is safe to use with clone_test_with_new_id.
+        self.__details = None
         self.__RunTest = kwargs.get('runTest', RunTest)
         self.__exception_handlers = []
         self.exception_handlers = [
@@ -114,6 +119,8 @@ class TestCase(unittest.TestCase):
         :param content_object: The content object for this detail. See
             testtools.content for more detail.
         """
+        if self.__details is None:
+            self.__details = {}
         self.__details[name] = content_object
 
     def getDetails(self):
@@ -121,6 +128,8 @@ class TestCase(unittest.TestCase):
 
         For more details see pydoc testtools.TestResult.
         """
+        if self.__details is None:
+            self.__details = {}
         return self.__details
 
     def patch(self, obj, attribute, value):
@@ -230,18 +239,10 @@ class TestCase(unittest.TestCase):
         :param observed: The observed value.
         :param message: An optional message to include in the error.
         """
-        try:
-            return super(TestCase, self).assertEqual(expected, observed)
-        except self.failureException:
-            lines = []
-            if message:
-                lines.append(message)
-            lines.extend(
-                ["not equal:",
-                 "a = %s" % pformat(expected),
-                 "b = %s" % pformat(observed),
-                 ''])
-            self.fail('\n'.join(lines))
+        matcher = Equals(expected)
+        if message:
+            matcher = Annotate(message, matcher)
+        self.assertThat(observed, matcher)
 
     failUnlessEqual = assertEquals = assertEqual
 
diff --git a/lib/testtools/testtools/tests/test_testtools.py b/lib/testtools/testtools/tests/test_testtools.py
index 9edc5a5..5dfb355 100644
--- a/lib/testtools/testtools/tests/test_testtools.py
+++ b/lib/testtools/testtools/tests/test_testtools.py
@@ -461,6 +461,15 @@ class TestAssertions(TestCase):
              'a = %s' % pformat(a),
              'b = %s' % pformat(b),
              ''])
+        expected_error = '\n'.join([
+            'Match failed. Matchee: "%r"' % b,
+            'Matcher: Annotate(%r, Equals(%r))' % (message, a),
+            'Difference: !=:',
+            'reference = %s' % pformat(a),
+            'actual = %s' % pformat(b),
+            ': ' + message,
+            ''
+            ])
         self.assertFails(expected_error, self.assertEqual, a, b, message)
         self.assertFails(expected_error, self.assertEquals, a, b, message)
         self.assertFails(expected_error, self.failUnlessEqual, a, b, message)
@@ -468,11 +477,12 @@ class TestAssertions(TestCase):
     def test_assertEqual_formatting_no_message(self):
         a = "cat"
         b = "dog"
-        expected_error = '\n'.join(
-            ['not equal:',
-             'a = %s' % pformat(a),
-             'b = %s' % pformat(b),
-             ''])
+        expected_error = '\n'.join([
+            'Match failed. Matchee: "dog"',
+            'Matcher: Equals(\'cat\')',
+            'Difference: \'cat\' != \'dog\'',
+            ''
+            ])
         self.assertFails(expected_error, self.assertEqual, a, b)
         self.assertFails(expected_error, self.assertEquals, a, b)
         self.assertFails(expected_error, self.failUnlessEqual, a, b)
@@ -760,6 +770,18 @@ class TestCloneTestWithNewId(TestCase):
         self.assertEqual(oldName, test.id(),
             "the original test instance should be unchanged.")
 
+    def test_cloned_testcase_does_not_share_details(self):
+        """A cloned TestCase does not share the details dict."""
+        class Test(TestCase):
+            def test_foo(self):
+                self.addDetail(
+                    'foo', content.Content('text/plain', lambda: 'foo'))
+        orig_test = Test('test_foo')
+        cloned_test = clone_test_with_new_id(orig_test, self.getUniqueString())
+        orig_test.run(unittest.TestResult())
+        self.assertEqual('foo', orig_test.getDetails()['foo'].iter_bytes())
+        self.assertEqual(None, cloned_test.getDetails().get('foo'))
+
 
 class TestDetailsProvided(TestWithDetails):
 
diff --git a/source4/lib/registry/pyregistry.c b/source4/lib/registry/pyregistry.c
index 7f4f833..1373ed8 100644
--- a/source4/lib/registry/pyregistry.c
+++ b/source4/lib/registry/pyregistry.c
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    Samba utility functions
    Copyright (C) Jelmer Vernooij <jelmer at samba.org> 2008
+   Copyright (C) Wilco Baan Hofman <wilco at baanhofman.nl> 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
@@ -238,16 +239,53 @@ static PyMethodDef hive_key_methods[] = {
 	{ NULL }
 };
 
-static PyObject *hive_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
-{
-	/* reg_open_hive */
+static PyObject *hive_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
 	Py_RETURN_NONE;
 }
 
+static PyObject *py_open_hive(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+	const char *kwnames[] = { "location", "lp_ctx", "session_info", "credentials", NULL };
+	WERROR result;
+	struct loadparm_context *lp_ctx;
+	PyObject *py_lp_ctx, *py_session_info, *py_credentials;
+	struct auth_session_info *session_info;
+	struct cli_credentials *credentials;
+	char *location;
+	struct hive_key *hive_key;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO",
+					 discard_const_p(char *, kwnames),
+	                                 &location,
+					 &py_lp_ctx, &py_session_info,
+					 &py_credentials))
+		return NULL;
+
+	lp_ctx = lpcfg_from_py_object(NULL, py_lp_ctx); /* FIXME: leaky */
+	if (lp_ctx == NULL) {
+		PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
+		return NULL;
+	}
+
+	credentials = cli_credentials_from_py_object(py_credentials);
+	if (credentials == NULL) {
+		PyErr_SetString(PyExc_TypeError, "Expected credentials");
+		return NULL;
+	}
+	session_info = NULL;
+
+	result = reg_open_hive(NULL, location, session_info, credentials,
+	                       tevent_context_init(NULL),
+	                       lp_ctx, &hive_key);
+	PyErr_WERROR_IS_ERR_RAISE(result);
+
+	return py_talloc_steal(&PyHiveKey, hive_key);
+}
+
 PyTypeObject PyHiveKey = {
 	.tp_name = "HiveKey",
 	.tp_methods = hive_key_methods,
-	.tp_new = hive_open,
+	.tp_new = hive_new,
 	.tp_basicsize = sizeof(py_talloc_Object),
 	.tp_dealloc = py_talloc_dealloc,
 	.tp_flags = Py_TPFLAGS_DEFAULT,
@@ -396,6 +434,7 @@ static PyMethodDef py_registry_methods[] = {
 	{ "open_directory", py_open_directory, METH_VARARGS, "open_dir(location) -> key" },
 	{ "create_directory", py_create_directory, METH_VARARGS, "create_dir(location) -> key" },
 	{ "open_ldb", (PyCFunction)py_open_ldb_file, METH_VARARGS|METH_KEYWORDS, "open_ldb(location, session_info=None, credentials=None, loadparm_context=None) -> key" },
+	{ "open_hive", (PyCFunction)py_open_hive, METH_VARARGS|METH_KEYWORDS, "open_hive(location, session_info=None, credentials=None, loadparm_context=None) -> key" },
 	{ "str_regtype", py_str_regtype, METH_VARARGS, "str_regtype(int) -> str" },
 	{ "get_predef_name", py_get_predef_name, METH_VARARGS, "get_predef_name(hkey) -> str" },
 	{ NULL }
diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c
index cfbaadd..b62109e 100644
--- a/source4/lib/registry/regf.c
+++ b/source4/lib/registry/regf.c
@@ -110,7 +110,7 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
 	hbin = hbin_by_offset(data, offset, &rel_offset);
 
 	if (hbin == NULL) {
-		DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
+		DEBUG(1, ("Can't find HBIN at 0x%04x\n", offset));
 		return ret;
 	}
 
@@ -216,6 +216,8 @@ static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
 	if (data->hbins[i] == NULL) {
 		DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
 			size));
+
+		/* Add extra hbin block */
 		data->hbins = talloc_realloc(data, data->hbins,
 					     struct hbin_block *, i+2);
 		hbin = talloc(data->hbins, struct hbin_block);
@@ -224,17 +226,22 @@ static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
 		data->hbins[i] = hbin;
 		data->hbins[i+1] = NULL;
 
+		/* Set hbin data */
 		hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
 		hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
 		hbin->offset_to_next = 0x1000;
 		hbin->unknown[0] = 0;
-		hbin->unknown[0] = 0;
+		hbin->unknown[1] = 0;
 		unix_to_nt_time(&hbin->last_change, time(NULL));
 		hbin->block_size = hbin->offset_to_next;
 		hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
+		/* Update the regf header */
+		data->header->last_block += hbin->offset_to_next;
 
-		rel_offset = 0x0;
+		/* Set the next block to it's proper size and set the
+		 * rel_offset for this block */
 		SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
+		rel_offset = 0x0;
 	}
 
 	/* Set size and mark as used */
@@ -314,7 +321,7 @@ static void hbin_free (struct regf_data *data, uint32_t offset)
 	size = -size;
 
 	/* If the next block is free, merge into big free block */
-	if (rel_offset + size < hbin->offset_to_next) {
+	if (rel_offset + size < hbin->offset_to_next - 0x20) {
 		next_size = IVALS(hbin->data, rel_offset+size);
 		if (next_size > 0) {
 			size += next_size;
@@ -489,7 +496,7 @@ static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
 
 	if (!hbin_get_tdr(regf, offset, nk,
 			  (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
-		DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
+		DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n", offset));
 		return NULL;
 	}
 
@@ -519,7 +526,8 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
 
 	tmp = hbin_get(regf, private_data->nk->values_offset);
 	if (!tmp.data) {
-		DEBUG(0, ("Unable to find value list\n"));
+		DEBUG(0, ("Unable to find value list at 0x%x\n",
+				private_data->nk->values_offset));
 		return WERR_GENERAL_FAILURE;
 	}
 
@@ -534,7 +542,7 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
 
 	if (!hbin_get_tdr(regf, vk_offset, vk,
 			  (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
-		DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
+		DEBUG(0, ("Unable to get VK block at 0x%x\n", vk_offset));
 		talloc_free(vk);
 		return WERR_GENERAL_FAILURE;
 	}
@@ -606,9 +614,15 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
 	if (idx >= nk->num_subkeys)
 		return WERR_NO_MORE_ITEMS;
 
+	/* Make sure that we don't crash if the key is empty */
+	if (nk->subkeys_offset == -1) {
+		return WERR_NO_MORE_ITEMS;
+	}
+
 	data = hbin_get(private_data->hive, nk->subkeys_offset);
 	if (!data.data) {
-		DEBUG(0, ("Unable to find subkey list\n"));
+		DEBUG(0, ("Unable to find subkey list at 0x%x\n",
+			nk->subkeys_offset));
 		return WERR_GENERAL_FAILURE;
 	}
 
@@ -845,6 +859,11 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
 	struct nk_block *nk = private_data->nk;
 	uint32_t key_off = 0;
 
+	/* Make sure that we don't crash if the key is empty */
+	if (nk->subkeys_offset == -1) {
+		return WERR_BADFILE;
+	}
+
 	data = hbin_get(private_data->hive, nk->subkeys_offset);
 	if (!data.data) {
 		DEBUG(0, ("Unable to find subkey list\n"));
@@ -1739,7 +1758,7 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
 
 	if (!hbin_get_tdr(regf, regf->header->data_offset, root,
 			  (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
-		DEBUG(0, ("Unable to find HBIN data for offset %d\n",
+		DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n",
 			regf->header->data_offset));
 		return WERR_GENERAL_FAILURE;
 	}
@@ -1764,6 +1783,7 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
 
 	*ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
 
+	DEBUG(9, ("Storing key %s\n", name));
 	return regf_save_hbin(private_data->hive);
 }
 
@@ -1789,7 +1809,7 @@ static WERROR regf_set_value(struct hive_key *key, const char *name,
 			if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
 					  (tdr_pull_fn_t)tdr_pull_vk_block,
 					  &vk)) {
-				DEBUG(0, ("Unable to get VK block at %d\n",
+				DEBUG(0, ("Unable to get VK block at 0x%x\n",
 					tmp_vk_offset));
 				return WERR_GENERAL_FAILURE;
 			}
diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl
index fd58ad2..064aaf0 100644
--- a/source4/lib/registry/regf.idl
+++ b/source4/lib/registry/regf.idl
@@ -74,8 +74,8 @@ interface regf
 	};
 
 	[noprint] enum reg_key_type { 
-		REG_ROOT_KEY = 0x20, 
-		REG_SUB_KEY  = 0x2C, 
+		REG_ROOT_KEY = 0x2C, 
+		REG_SUB_KEY  = 0x20, 
 		REG_SYM_LINK = 0x10 
 	};
 


-- 
Samba Shared Repository


More information about the samba-cvs mailing list