subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1509228 - /subversion/branches/fsx/subversion/tests/libsvn_subr/packed-data-test.c
Date Thu, 01 Aug 2013 13:27:31 GMT
Author: stefan2
Date: Thu Aug  1 13:27:31 2013
New Revision: 1509228

URL: http://svn.apache.org/r1509228
Log:
On the fsx branch: Implement various tests for the svn_packed_data__* API.

* subversion/tests/libsvn_subr/packed-data-test.c
  (get_read_root): document
  (sub_record_t,
   base_record_t,
   SUB_RECORD_COUNT,
   BASE_RECORD_COUNT,
   sub_records,
   test_data): new test data
  (verify_uint_stream,
   verify_int_stream,
   pack_subs,
   pack,
   unpack_subs,
   unpack,
   compare_binary,
   compare_subs,
   compare): new utility functions
  (test_uint_stream,
   test_int_stream,
   test_byte_stream,
   test_empty_structure,
   test_full_structure): new test functions
  (test_funcs): register new tests

Modified:
    subversion/branches/fsx/subversion/tests/libsvn_subr/packed-data-test.c

Modified: subversion/branches/fsx/subversion/tests/libsvn_subr/packed-data-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/fsx/subversion/tests/libsvn_subr/packed-data-test.c?rev=1509228&r1=1509227&r2=1509228&view=diff
==============================================================================
--- subversion/branches/fsx/subversion/tests/libsvn_subr/packed-data-test.c (original)
+++ subversion/branches/fsx/subversion/tests/libsvn_subr/packed-data-test.c Thu Aug  1 13:27:31
2013
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <apr_pools.h>
+#include <apr_poll.h>
 
 #include "../svn_test.h"
 
@@ -38,6 +39,9 @@
 #include "svn_string.h"   /* This includes <apr_*.h> */
 #include "private/svn_packed_data.h"
 
+/* Take the WRITE_ROOT, serialize its contents, parse it again into a new
+ * data root and return it in *READ_ROOT.  Allocate it in POOL.
+ */
 static svn_error_t*
 get_read_root(svn_packed__data_root_t **read_root,
               svn_packed__data_root_t *write_root,
@@ -71,11 +75,493 @@ test_empty_container(apr_pool_t *pool)
   return SVN_NO_ERROR;
 }
 
+/* Check that COUNT numbers from VALUES can be written as uints to a
+ * packed data stream and can be read from that stream again.  Deltify
+ * data in the stream if DIFF is set.  Use POOL for allocations.
+ */
+static svn_error_t *
+verify_uint_stream(const apr_uint64_t *values,
+                   apr_size_t count,
+                   svn_boolean_t diff,
+                   apr_pool_t *pool)
+{
+  svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+  svn_packed__int_stream_t *stream
+    = svn_packed__create_int_stream(root, diff, FALSE);
+
+  apr_size_t i;
+  for (i = 0; i < count; ++i)
+    svn_packed__add_uint(stream, values[i]);
+
+  SVN_ERR(get_read_root(&root, root, pool));
+
+  /* the container should contain exactly one int stream */
+  stream = svn_packed__first_int_stream(root);
+  SVN_TEST_ASSERT(stream);
+  SVN_TEST_ASSERT(!svn_packed__next_int_stream(stream));
+  SVN_TEST_ASSERT(!svn_packed__first_byte_stream(root));
+  
+  /* the stream shall contain exactly the items we put into it */
+  SVN_TEST_ASSERT(svn_packed__int_count(stream) == count);
+  for (i = 0; i < count; ++i)
+    SVN_TEST_ASSERT(svn_packed__get_uint(stream) == values[i]);
+
+  /* reading beyond eos should return 0 values */
+  SVN_TEST_ASSERT(svn_packed__get_uint(stream) == 0);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_uint_stream(apr_pool_t *pool)
+{
+  enum { COUNT = 8 };
+  const apr_uint64_t values[COUNT] =
+  {
+    0xffffffffffffffffull,
+    0,
+    0xffffffffffffffffull,
+    0x8000000000000000ull,
+    0,
+    0x7fffffffffffffffull,
+    0x1234567890abcdefull,
+    0x0fedcba987654321ull,
+  };
+
+  SVN_ERR(verify_uint_stream(values, COUNT, FALSE, pool));
+  SVN_ERR(verify_uint_stream(values, COUNT, TRUE, pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Check that COUNT numbers from VALUES can be written as signed ints to a
+ * packed data stream and can be read from that stream again.  Deltify
+ * data in the stream if DIFF is set.  Use POOL for allocations.
+ */
+static svn_error_t *
+verify_int_stream(const apr_int64_t *values,
+                  apr_size_t count,
+                  svn_boolean_t diff,
+                  apr_pool_t *pool)
+{
+  svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+  svn_packed__int_stream_t *stream
+    = svn_packed__create_int_stream(root, diff, TRUE);
+
+  apr_size_t i;
+  for (i = 0; i < count; ++i)
+    svn_packed__add_int(stream, values[i]);
+
+  SVN_ERR(get_read_root(&root, root, pool));
+
+  /* the container should contain exactly one int stream */
+  stream = svn_packed__first_int_stream(root);
+  SVN_TEST_ASSERT(stream);
+  SVN_TEST_ASSERT(!svn_packed__next_int_stream(stream));
+  SVN_TEST_ASSERT(!svn_packed__first_byte_stream(root));
+
+  /* the stream shall contain exactly the items we put into it */
+  SVN_TEST_ASSERT(svn_packed__int_count(stream) == count);
+  for (i = 0; i < count; ++i)
+    SVN_TEST_ASSERT(svn_packed__get_int(stream) == values[i]);
+
+  /* reading beyond eos should return 0 values */
+  SVN_TEST_ASSERT(svn_packed__get_int(stream) == 0);
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_int_stream(apr_pool_t *pool)
+{
+  enum { COUNT = 7 };
+  const apr_int64_t values[COUNT] =
+  {
+     0x7fffffffffffffffll,
+    -0x8000000000000000ll,
+     0,
+     0x7fffffffffffffffll,
+    -0x7fffffffffffffffll,
+     0x1234567890abcdefll,
+    -0x0fedcba987654321ll,
+  };
+
+  SVN_ERR(verify_int_stream(values, COUNT, FALSE, pool));
+  SVN_ERR(verify_int_stream(values, COUNT, TRUE, pool));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_byte_stream(apr_pool_t *pool)
+{
+  enum { COUNT = 6 };
+  const svn_string_t values[COUNT] =
+  {
+    { "", 0 },
+    { "\0", 1 },
+    { "\0", 1 },
+    { "some text", 9 },
+    { "", 0 },
+    { "some more", 9 }
+  };
+
+  svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+  svn_packed__byte_stream_t *stream
+    = svn_packed__create_bytes_stream(root);
+
+  apr_size_t i;
+  for (i = 0; i < COUNT; ++i)
+    svn_packed__add_bytes(stream, values[i].data, values[i].len);
+
+  SVN_ERR(get_read_root(&root, root, pool));
+
+  /* the container should contain exactly one byte stream */
+  stream = svn_packed__first_byte_stream(root);
+  SVN_TEST_ASSERT(stream);
+  SVN_TEST_ASSERT(!svn_packed__next_byte_stream(stream));
+
+  /* the stream shall contain exactly the items we put into it */
+  SVN_TEST_ASSERT(svn_packed__byte_count(stream) == 20);
+  for (i = 0; i < COUNT; ++i)
+    {
+      svn_string_t string;
+      string.data = svn_packed__get_bytes(stream, &string.len);
+
+      SVN_TEST_ASSERT(string.len == values[i].len);
+      SVN_TEST_ASSERT(!memcmp(string.data, values[i].data, string.len));
+    }
+
+  /* reading beyond eos should return 0 values */
+  SVN_TEST_ASSERT(svn_packed__byte_count(stream) == 0);
+
+  return SVN_NO_ERROR;
+}
+
+/* Some simple structure that we use as sub-structure to BASE_RECORD_T.
+ * Have it contain numbers and strings.
+ */
+typedef struct sub_record_t
+{
+  int sub_counter;
+  svn_string_t text;
+} sub_record_t;
+
+/* signed / unsigned, 64 bits and shorter, diff-able and not, multiple
+ * strings, multiple sub-records. */
+typedef struct base_record_t
+{
+  int counter;
+  svn_string_t description;
+  apr_uint64_t large_unsigned1;
+  apr_uint64_t large_unsigned2;
+  const sub_record_t *left_subs;
+  apr_int64_t large_signed1;
+  apr_int64_t large_signed2;
+  unsigned prime;
+  const sub_record_t *right_subs;
+  svn_string_t binary;
+} base_record_t;
+
+/* our test data */
+enum {SUB_RECORD_COUNT = 7};
+enum {BASE_RECORD_COUNT = 4};
+
+const sub_record_t sub_records[SUB_RECORD_COUNT] =
+{
+  { 6, { "this is quite a longish piece of text", 37} },
+  { 5, { "x", 1} },
+  { 4, { "not empty", 9} },
+  { 3, { "another bit of text", 19} },
+  { 2, { "", 0} },
+  { 1, { "first sub-record", 16} },
+  { 0 }
+};
+
+const base_record_t test_data[BASE_RECORD_COUNT] =
+{
+  { 1, { "maximum", 7},
+    0xffffffffffffffffull, 0xffffffffffffffffull, sub_records,
+    0x7fffffffffffffffll,  0x7fffffffffffffffll, 9967, sub_records + 1,
+    { "\0\1\2\3\4\5\6\7\x8\x9\xa", 11} },
+  { 2, { "minimum", 7},
+    0, 0, sub_records + 6,
+    -0x8000000000000000ll, -0x8000000000000000ll, 6029, sub_records + 5,
+    { "X\0\0Y", 4} },
+  { 3, { "mean", 4},
+    0x8000000000000000ull, 0x8000000000000000ull, sub_records + 2,
+    0, 0, 653, sub_records + 3,
+    { "\xff\0\1\2\3\4\5\6\7\x8\x9\xa", 12} },
+  { 4, { "random", 6},
+    0x1234567890abcdefull, 0xfedcba987654321ull, sub_records + 4,
+    0x1234567890abcdll, -0xedcba987654321ll, 7309, sub_records + 1,
+    { "\x80\x7f\0\1\6", 5} }
+};
+
+/* Serialize RECORDS into INT_STREAM and TEXT_STREAM.  Stop when the
+ * current record's SUB_COUNTER is 0.
+ */
+static unsigned
+pack_subs(svn_packed__int_stream_t *int_stream,
+          svn_packed__byte_stream_t *text_stream,
+          const sub_record_t *records)
+{
+  unsigned count;
+  for (count = 0; records[count].sub_counter; ++count)
+    {
+      svn_packed__add_int(int_stream, records[count].sub_counter);
+      svn_packed__add_bytes(text_stream,
+                            records[count].text.data,
+                            records[count].text.len);
+    }
+
+  return count;
+}
+
+/* Serialize COUNT records starting from DATA into a packed data container
+ * allocated in POOL and return the container root.
+ */
+static svn_packed__data_root_t *
+pack(const base_record_t *data,
+     apr_size_t count,
+     apr_pool_t *pool)
+{
+  apr_size_t i;
+  svn_packed__data_root_t *root = svn_packed__data_create_root(pool);
+  svn_packed__int_stream_t *base_stream
+    = svn_packed__create_int_stream(root, FALSE, FALSE);
+  svn_packed__int_stream_t *sub_count_stream
+    = svn_packed__create_int_stream(root, TRUE, FALSE);
+
+  svn_packed__int_stream_t *left_sub_stream
+    = svn_packed__create_int_stream(root, FALSE, TRUE);
+  svn_packed__int_stream_t *right_sub_stream
+    = svn_packed__create_int_stream(root, FALSE, TRUE);
+
+  svn_packed__byte_stream_t *base_description_stream
+    = svn_packed__create_bytes_stream(root);
+  svn_packed__byte_stream_t *base_binary_stream
+    = svn_packed__create_bytes_stream(root);
+  svn_packed__byte_stream_t *sub_text_stream
+    = svn_packed__create_bytes_stream(root);
+
+  svn_packed__create_int_substream(base_stream, TRUE, TRUE);   /* counter */
+  svn_packed__create_int_substream(base_stream, TRUE, FALSE);  /* large_unsigned1 */
+  svn_packed__create_int_substream(base_stream, FALSE, FALSE); /* large_unsigned2 */
+  svn_packed__create_int_substream(base_stream, TRUE, TRUE);   /* large_signed1 */
+  svn_packed__create_int_substream(base_stream, FALSE, TRUE);  /* large_signed2 */
+  svn_packed__create_int_substream(base_stream, TRUE, FALSE);  /* prime */
+  
+  for (i = 0; i < count; ++i)
+    {
+      svn_packed__add_int(base_stream, data[i].counter);
+      svn_packed__add_bytes(base_description_stream,
+                            data[i].description.data,
+                            data[i].description.len);
+      svn_packed__add_uint(base_stream, data[i].large_unsigned1);
+      svn_packed__add_uint(base_stream, data[i].large_unsigned2);
+      svn_packed__add_uint(sub_count_stream,
+                           pack_subs(left_sub_stream, sub_text_stream,
+                                     data[i].left_subs));
+
+      svn_packed__add_int(base_stream, data[i].large_signed1);
+      svn_packed__add_int(base_stream, data[i].large_signed2);
+      svn_packed__add_uint(base_stream, data[i].prime);
+      svn_packed__add_uint(sub_count_stream,
+                           pack_subs(right_sub_stream, sub_text_stream,
+                                     data[i].right_subs));
+
+      svn_packed__add_bytes(base_binary_stream,
+                            data[i].binary.data,
+                            data[i].binary.len);
+    }
+
+  return root;
+}
+
+/* Deserialize COUNT records from INT_STREAM and TEXT_STREAM and return
+ * the result allocated in POOL.
+ */
+static sub_record_t *
+unpack_subs(svn_packed__int_stream_t *int_stream,
+            svn_packed__byte_stream_t *text_stream,
+            apr_size_t count,
+            apr_pool_t *pool)
+{
+  sub_record_t *records = apr_pcalloc(pool, (count + 1) * sizeof(*records));
+
+  apr_size_t i;
+  for (i = 0; i < count; ++i)
+    {
+      records[i].sub_counter = svn_packed__get_int(int_stream);
+      records[i].text.data = svn_packed__get_bytes(text_stream,
+                                                   &records[i].text.len);
+    }
+
+  return records;
+}
+
+/* Deserialize all records from the packed data container ROOT, allocate
+ * them in POOL and return them.  Set *COUNT to the number of records read.
+ */
+static base_record_t *
+unpack(apr_size_t *count,
+       svn_packed__data_root_t *root,
+       apr_pool_t *pool)
+{
+  svn_packed__int_stream_t *base_stream
+    = svn_packed__first_int_stream(root);
+  svn_packed__int_stream_t *sub_count_stream
+    = svn_packed__next_int_stream(base_stream);
+  svn_packed__byte_stream_t *base_description_stream
+    = svn_packed__first_byte_stream(root);
+  svn_packed__byte_stream_t *base_binary_stream
+    = svn_packed__next_byte_stream(base_description_stream);
+  svn_packed__byte_stream_t *sub_text_stream
+    = svn_packed__next_byte_stream(base_binary_stream);
+
+  svn_packed__int_stream_t *left_sub_stream
+    = svn_packed__next_int_stream(sub_count_stream);
+  svn_packed__int_stream_t *right_sub_stream
+    = svn_packed__next_int_stream(left_sub_stream);
+
+  apr_size_t i;
+  base_record_t *data;
+  *count = svn_packed__int_count(sub_count_stream) / 2;
+  data = apr_pcalloc(pool, *count * sizeof(*data));
+  
+  for (i = 0; i < *count; ++i)
+    {
+      data[i].counter = svn_packed__get_int(base_stream);
+      data[i].description.data
+        = svn_packed__get_bytes(base_description_stream,
+                                &data[i].description.len);
+      data[i].large_unsigned1 = svn_packed__get_uint(base_stream);
+      data[i].large_unsigned2 = svn_packed__get_uint(base_stream);
+      data[i].left_subs = unpack_subs(left_sub_stream, sub_text_stream,
+                      (apr_size_t)svn_packed__get_uint(sub_count_stream),
+                      pool);
+
+      data[i].large_signed1 = svn_packed__get_int(base_stream);
+      data[i].large_signed2 = svn_packed__get_int(base_stream);
+      data[i].prime = svn_packed__get_uint(base_stream);
+      data[i].right_subs = unpack_subs(right_sub_stream, sub_text_stream,
+                      (apr_size_t)svn_packed__get_uint(sub_count_stream),
+                      pool);
+
+      data[i].binary.data
+        = svn_packed__get_bytes(base_binary_stream,
+                                &data[i].binary.len);
+    }
+
+  return data;
+}
+
+/* Assert that LHS and RHS contain the same binary data (i.e. don't test
+ * for a terminating NUL).
+ */
+static svn_error_t *
+compare_binary(const svn_string_t *lhs,
+               const svn_string_t *rhs)
+{
+  SVN_TEST_ASSERT(lhs->len == rhs->len);
+  SVN_TEST_ASSERT(!memcmp(lhs->data, rhs->data, rhs->len));
+
+  return SVN_NO_ERROR;
+}
+
+/* Assert that LHS and RHS contain the same number of records with the
+ * same contents.
+ */
+static svn_error_t *
+compare_subs(const sub_record_t *lhs,
+             const sub_record_t *rhs)
+{
+  for (; lhs->sub_counter; ++lhs, ++rhs)
+    {
+      SVN_TEST_ASSERT(lhs->sub_counter == rhs->sub_counter);
+      SVN_ERR(compare_binary(&lhs->text, &rhs->text));
+    }
+
+  SVN_TEST_ASSERT(lhs->sub_counter == rhs->sub_counter);
+  return SVN_NO_ERROR;
+}
+
+/* Assert that the first COUNT records in LHS and RHS have the same contents.
+ */
+static svn_error_t *
+compare(const base_record_t *lhs,
+        const base_record_t *rhs,
+        apr_size_t count)
+{
+  apr_size_t i;
+  for (i = 0; i < count; ++i)
+    {
+      SVN_TEST_ASSERT(lhs[i].counter == rhs[i].counter);
+      SVN_ERR(compare_binary(&lhs[i].description, &rhs[i].description));
+      SVN_TEST_ASSERT(lhs[i].large_unsigned1 == rhs[i].large_unsigned1);
+      SVN_TEST_ASSERT(lhs[i].large_unsigned2 == rhs[i].large_unsigned2);
+      SVN_ERR(compare_subs(lhs[i].left_subs, rhs[i].left_subs));
+      SVN_TEST_ASSERT(lhs[i].counter == rhs[i].counter);
+      SVN_TEST_ASSERT(lhs[i].large_signed1 == rhs[i].large_signed1);
+      SVN_TEST_ASSERT(lhs[i].large_signed2 == rhs[i].large_signed2);
+      SVN_TEST_ASSERT(lhs[i].prime == rhs[i].prime);
+      SVN_ERR(compare_subs(lhs[i].right_subs, rhs[i].right_subs));
+      SVN_ERR(compare_binary(&lhs[i].binary, &rhs[i].binary));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_empty_structure(apr_pool_t *pool)
+{
+  base_record_t *unpacked;
+  apr_size_t count;
+
+  /* create an empty, readable container */
+  svn_packed__data_root_t *root = pack(test_data, 0, pool);
+
+  SVN_ERR(get_read_root(&root, root, pool));
+  unpacked = unpack(&count, root, pool);
+  SVN_TEST_ASSERT(count == 0);
+  SVN_ERR(compare(unpacked, test_data, count));
+
+  return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+test_full_structure(apr_pool_t *pool)
+{
+  base_record_t *unpacked;
+  apr_size_t count;
+
+  /* create an empty, readable container */
+  svn_packed__data_root_t *root = pack(test_data, BASE_RECORD_COUNT, pool);
+
+  SVN_ERR(get_read_root(&root, root, pool));
+  unpacked = unpack(&count, root, pool);
+  SVN_TEST_ASSERT(count == BASE_RECORD_COUNT);
+  SVN_ERR(compare(unpacked, test_data, count));
+
+  return SVN_NO_ERROR;
+}
+
 /* An array of all test functions */
 struct svn_test_descriptor_t test_funcs[] =
   {
     SVN_TEST_NULL,
     SVN_TEST_PASS2(test_empty_container,
                    "test empty container"),
+    SVN_TEST_PASS2(test_uint_stream,
+                   "test a single uint stream"),
+    SVN_TEST_PASS2(test_int_stream,
+                   "test a single int stream"),
+    SVN_TEST_PASS2(test_byte_stream,
+                   "test a single bytes stream"),
+    SVN_TEST_PASS2(test_empty_structure,
+                   "test empty, nested structure"),
+    SVN_TEST_PASS2(test_full_structure,
+                   "test nested structure"),
     SVN_TEST_NULL
   };



Mime
View raw message