Include a mapitest test suite / challenge for lzxpress
authorJulien Kerihuel <j.kerihuel@openchange.org>
Fri, 27 Aug 2010 10:43:21 +0000 (10:43 +0000)
committerJulien Kerihuel <j.kerihuel@openchange.org>
Fri, 27 Aug 2010 10:43:21 +0000 (10:43 +0000)
The idea of this test is to check if lzxpress compressed blobs
provided by OpenChange are the same than Outlook ones. The test takes
a Outlook->Exchange capture file with compressed blob, pull the
content, decompressed the content, recompress the content and check
the output for differing bytes.

This challenge code should give us good information when lzxpress
compress code is fixed. Additionally you can uncomment the compression
code in libmapi/emsmdb.c to do further testing.

Makefile
config.mk.in
utils/mapitest/data/lzxpress/001_Outlook_2007_in_ModifyRecipients_comp.dat [new file with mode: 0644]
utils/mapitest/data/lzxpress/002_Outlook_2007_in_Tables_operations_comp.dat [new file with mode: 0644]
utils/mapitest/module.c
utils/mapitest/modules/module_lzxpress.c [new file with mode: 0644]

index 7a6952e31e20213030c4d0a73d8113b8e16d2baf..3ff2961b0d01985987cf2929a3c6cf0f7e8ec873 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1339,9 +1339,12 @@ mapitest:        libmapi                 \
 mapitest-install:      mapitest
        $(INSTALL) -d $(DESTDIR)$(bindir)
        $(INSTALL) -m 0755 bin/mapitest $(DESTDIR)$(bindir)
+       $(INSTALL) -d $(DESTDIR)$(datadir)/mapitest/lzxpress
+       $(INSTALL) -m 0644 utils/mapitest/data/lzxpress/* $(DESTDIR)$(datadir)/mapitest/lzxpress/
 
 mapitest-uninstall:
        rm -f $(DESTDIR)$(bindir)/mapitest
+       rm -rf $(DESTDIR)$(datadir)/mapitest
 
 mapitest-clean:
        rm -f bin/mapitest
@@ -1380,6 +1383,7 @@ bin/mapitest:     utils/mapitest/mapitest.o                       \
                utils/mapitest/modules/module_errorchecks.o     \
                utils/mapitest/modules/module_lcid.o            \
                utils/mapitest/modules/module_mapidump.o        \
+               utils/mapitest/modules/module_lzxpress.o        \
                libmapi.$(SHLIBEXT).$(PACKAGE_VERSION)          
        @echo "Linking $@"
        @$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) -lpopt $(SUBUNIT_LIBS)
@@ -1404,7 +1408,8 @@ utils/mapitest/proto.h:                                   \
        utils/mapitest/modules/module_noserver.c        \
        utils/mapitest/modules/module_errorchecks.c     \
        utils/mapitest/modules/module_lcid.c            \
-       utils/mapitest/modules/module_mapidump.c
+       utils/mapitest/modules/module_mapidump.c        \
+       utils/mapitest/modules/module_lzxpress.c
        @echo "Generating $@"
        @./script/mkproto.pl --private=utils/mapitest/mapitest_proto.h --public=utils/mapitest/proto.h $^
 
index e368e72dd0031309dce74a216c85ce365dd63313..741ef230739df42d71b8907c5cb1d54aa533d49f 100644 (file)
@@ -34,7 +34,8 @@ CFLAGS=@CFLAGS@ @COMPILER_OPTIONS_C@ @ASSERT_DEFINITION@ @SUBUNIT_CFLAGS@ \
        -DDEFAULT_LDIF=\"$(datadir)/setup/profiles\"                                            \
        -DMAPISTORE_LDIF=\"$(datadir)/setup/mapistore\"                                         \
        -DMAPISTORE_BACKEND_INSTALLDIR=\"$(libdir)/mapistore_backends\"                         \
-       -DMAPISTORE_MAPPING_PATH=\"$(prefix)/private/mapistore\"
+       -DMAPISTORE_MAPPING_PATH=\"$(prefix)/private/mapistore\"                                        \
+       -DLZXPRESS_DATADIR=\"$(datadir)/mapitest/lzxpress\"
 
 # This value should be determined by configure at some point
 SHLIBEXT=so
diff --git a/utils/mapitest/data/lzxpress/001_Outlook_2007_in_ModifyRecipients_comp.dat b/utils/mapitest/data/lzxpress/001_Outlook_2007_in_ModifyRecipients_comp.dat
new file mode 100644 (file)
index 0000000..119c40d
Binary files /dev/null and b/utils/mapitest/data/lzxpress/001_Outlook_2007_in_ModifyRecipients_comp.dat differ
diff --git a/utils/mapitest/data/lzxpress/002_Outlook_2007_in_Tables_operations_comp.dat b/utils/mapitest/data/lzxpress/002_Outlook_2007_in_Tables_operations_comp.dat
new file mode 100644 (file)
index 0000000..d4b8b66
Binary files /dev/null and b/utils/mapitest/data/lzxpress/002_Outlook_2007_in_Tables_operations_comp.dat differ
index 8e5a00da18eb8cbd770b838b40503af1338cedfc..0a930f157cbe70fdbb5a15016465e3ec408e3197 100644 (file)
@@ -41,6 +41,7 @@ _PUBLIC_ uint32_t mapitest_register_modules(struct mapitest *mt)
        ret += module_errorchecks_init(mt);
        ret += module_lcid_init(mt);
        ret += module_mapidump_init(mt);
+       ret += module_lzxpress_init(mt);
 
        return ret;
 }
@@ -456,3 +457,24 @@ _PUBLIC_ uint32_t module_mapidump_init(struct mapitest *mt)
 
        return MAPITEST_SUCCESS;
 }
+
+
+/**
+   \details Initialise the language code / ID test suite
+
+   \param mt pointer to the top-level mapitest structure
+
+   \return MAPITEST_SUCCESS on success, otherwise MAPITEST_ERROR
+ */
+_PUBLIC_ uint32_t module_lzxpress_init(struct mapitest *mt)
+{
+       struct mapitest_suite   *suite = NULL;
+
+       suite = mapitest_suite_init(mt, "LZXPRESS", "lzxpress algorithm test suite", false);
+
+       mapitest_suite_add_test(suite, "VALIDATE-001", "Validate LZXPRESS implementation using sample file 001", mapitest_lzxpress_validate_test_001);
+
+       mapitest_suite_register(mt, suite);
+
+       return MAPITEST_SUCCESS;
+}
diff --git a/utils/mapitest/modules/module_lzxpress.c b/utils/mapitest/modules/module_lzxpress.c
new file mode 100644 (file)
index 0000000..d5c0609
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+   Stand-alone MAPI testsuite
+
+   OpenChange Project - LZXPRESS compression/decompression
+
+   Copyright (C) Julien Kerihuel 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 "utils/mapitest/mapitest.h"
+#include "utils/mapitest/proto.h"
+#include "gen_ndr/ndr_exchange.h"
+#include "libmapi/libmapi_private.h"
+
+/**
+   \file module_lzxpress.c
+
+   \brief LZXPRESS compression and decompression test suite
+ */
+
+
+_PUBLIC_ bool mapitest_lzxpress_validate_test_001(struct mapitest *mt)
+{
+       bool                    ret = false;
+       char                    *filename = NULL;
+       DATA_BLOB               blob;
+       uint8_t                 *data;
+       size_t                  size;
+       struct ndr_print        *ndr_print;
+       struct ndr_pull         *ndr_pull;
+       struct ndr_push         *ndr_push;
+       struct ndr_push         *ndr_comp;
+       struct ndr_push         *ndr_rgbIn;
+       struct RPC_HEADER_EXT   RPC_HEADER_EXT;
+       struct EcDoRpcExt2      r;
+       struct mapi2k7_request  request;
+       NTSTATUS                status;
+       enum ndr_err_code       ndr_err;
+
+       /* Step 1. Load Test File 001_Outlook_2007_in_ModifyRecipients_comp.dat */
+       filename = talloc_asprintf(mt->mem_ctx, "%s/001_Outlook_2007_in_ModifyRecipients_comp.dat", LZXPRESS_DATADIR);
+/*     filename = talloc_asprintf(mt->mem_ctx, "%s/002_Outlook_2007_in_Tables_operations_comp.dat", LZXPRESS_DATADIR); */
+       data = (uint8_t *)file_load(filename, &size, 0, mt->mem_ctx);
+       if (!data) {
+               perror(filename);
+               mapitest_print_retval_fmt(mt, "lzxpress_validate", "Error while loading %s", filename);
+               talloc_free(filename);
+               return false;
+       }
+       blob.data = data;
+       blob.length = size;
+       mapitest_print_retval_step(mt, "1", "Loading 001_Outlook_2007_in_ModifyRecipients_comp.dat", MAPI_E_SUCCESS);
+
+       ndr_print = talloc_zero(mt->mem_ctx, struct ndr_print);
+       ndr_print->print = ndr_print_debug_helper;
+       ndr_print->depth = 1;
+
+       /* Step 2. Pull 001_Outlook_2007_in_ModifyRecipients_comp.dat data */
+       ndr_pull = ndr_pull_init_blob(&blob, mt->mem_ctx);
+       ndr_pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+
+       ndr_err = ndr_pull_EcDoRpcExt2(ndr_pull, NDR_IN, &r);
+       talloc_free(ndr_pull);
+       status = ndr_map_error2ntstatus(ndr_err);
+       if (NT_STATUS_IS_OK(status)) {
+               mapitest_print_retval_step(mt, "2", "001_Outlook_2007_in_ModifyRecipients_comp.dat", 
+                                          MAPI_E_SUCCESS);
+       } else {
+               mapitest_print_retval_step(mt, "2", "Pulling 001_Outlook_2007_in_ModifyRecipients_comp.dat", 
+                                          MAPI_E_CALL_FAILED);
+               return false;
+       }
+
+       /* Step 4. Decompress data */
+       blob.data = talloc_memdup(mt->mem_ctx, r.in.rgbIn, r.in.cbIn);
+       blob.length = r.in.cbIn;
+       ndr_pull = ndr_pull_init_blob(&blob, mt->mem_ctx);
+       ndr_set_flags(&ndr_pull->flags, LIBNDR_FLAG_NOALIGN|LIBNDR_FLAG_REF_ALLOC);
+       ndr_err = ndr_pull_mapi2k7_request(ndr_pull, NDR_SCALARS|NDR_BUFFERS, &request);
+       talloc_free(blob.data);
+       talloc_free(ndr_pull);
+       status = ndr_map_error2ntstatus(ndr_err);
+       if (NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Success\n"));
+       }
+
+       /* Step 5. Recompress data */
+       ndr_push = ndr_push_init_ctx(mt->mem_ctx);
+       ndr_set_flags(&ndr_push->flags, LIBNDR_FLAG_NOALIGN|LIBNDR_FLAG_REF_ALLOC);
+       ndr_push_mapi_request(ndr_push, NDR_SCALARS|NDR_BUFFERS, request.mapi_request);
+       ndr_comp = ndr_push_init_ctx(mt->mem_ctx);
+       ndr_push_lzxpress_compress(ndr_comp, ndr_push);
+       
+       /* Recreate complete blob */
+       ndr_rgbIn = ndr_push_init_ctx(mt->mem_ctx);
+       ndr_set_flags(&ndr_rgbIn->flags, LIBNDR_FLAG_NOALIGN|LIBNDR_FLAG_REF_ALLOC);
+
+       RPC_HEADER_EXT.Version = 0x0000;
+       RPC_HEADER_EXT.Flags = RHEF_Compressed|RHEF_Last;
+       RPC_HEADER_EXT.Size = ndr_comp->offset;
+       RPC_HEADER_EXT.SizeActual = ndr_push->offset;
+       ndr_push_RPC_HEADER_EXT(ndr_rgbIn, NDR_SCALARS|NDR_BUFFERS, &RPC_HEADER_EXT);
+
+       ndr_push_bytes(ndr_rgbIn, ndr_comp->data, ndr_comp->offset);
+       talloc_free(ndr_comp);
+
+       /* Compare Outlook and openchange rgbIn compressed blob */
+       DEBUG(0, ("Outlook    compressed blob size = 0x%x\n", r.in.cbIn));
+       DEBUG(0, ("OpenChange compressed blob size = 0x%x\n", ndr_rgbIn->offset));
+       ret = true;
+       {
+               int i;
+               int min;
+
+               min = (ndr_rgbIn->offset >= r.in.cbIn) ? r.in.cbIn : ndr_rgbIn->offset;
+               DEBUG(0, ("Comparing Outlook and OpenChange blobs on 0x%x bytes\n", min));
+               for (i = 0; i < min; i++) {
+                       if (r.in.rgbIn[i] != ndr_rgbIn->data[i]) {
+                               DEBUG(0, ("Bytes differs at offset 0x%x: Outlook (0x%.2x) OpenChange (0x%.2x)\n", 
+                                         i, r.in.rgbIn[i], ndr_rgbIn->data[i]));
+                               ret = false;
+                       }
+               }
+               
+       }
+
+       mapitest_print(mt, "Compressed rgbIn by Outlook\n");
+       mapitest_print(mt, "==============================\n");
+       dump_data(0, r.in.rgbIn, r.in.cbIn);
+       mapitest_print(mt, "==============================\n");
+
+       mapitest_print(mt, "Compressed rgbIn by OpenChange\n");
+       mapitest_print(mt, "==============================\n");
+       dump_data(0, ndr_rgbIn->data, ndr_rgbIn->offset);
+       mapitest_print(mt, "==============================\n");
+
+       talloc_free(ndr_rgbIn);
+
+       return ret;
+}