Index: /trunk/src/VBox/Devices/Storage/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Devices/Storage/testcase/Makefile.kmk	(revision 31192)
+++ /trunk/src/VBox/Devices/Storage/testcase/Makefile.kmk	(revision 31193)
@@ -5,5 +5,5 @@
 
 #
-# Copyright (C) 2006-2007 Oracle Corporation
+# Copyright (C) 2006-2010 Oracle Corporation
 #
 # This file is part of VirtualBox Open Source Edition (OSE), as
@@ -49,5 +49,5 @@
 #
 ifdef VBOX_WITH_TESTCASES
- PROGRAMS += tstVD tstVD-2 tstVDCopy tstVDSnap
+ PROGRAMS += tstVD tstVD-2 tstVDCopy tstVDSnap tstVDShareable
  ifeq ($(KBUILD_TARGET),l4)
   tstVD_TEMPLATE = VBOXLNXHOSTR3EXE
@@ -55,4 +55,5 @@
   tstVDCopy_TEMPLATE = VBOXLNXHOSTR3EXE
   tstVDSnap_TEMPLATE = VBOXLNXHOSTR3EXE
+  tstVDShareable_TEMPLATE = VBOXLNXHOSTR3EXE
  else
   tstVD_TEMPLATE = VBOXR3TSTEXE
@@ -60,4 +61,5 @@
   tstVDCopy_TEMPLATE = VBOXR3TSTEXE
   tstVDSnap_TEMPLATE = VBOXR3TSTEXE
+  tstVDShareable_TEMPLATE = VBOXR3TSTEXE
  endif
  tstVD_LIBS     = $(LIB_DDU) $(LIB_RUNTIME)
@@ -65,8 +67,10 @@
  tstVDCopy_LIBS   = $(LIB_DDU) $(LIB_RUNTIME)
  tstVDSnap_LIBS   = $(LIB_DDU) $(LIB_RUNTIME)
+ tstVDShareable_LIBS   = $(LIB_DDU) $(LIB_RUNTIME)
  tstVD_SOURCES  = tstVD.cpp
  tstVD-2_SOURCES  = tstVD-2.cpp
  tstVDCopy_SOURCES  = tstVDCopy.cpp
  tstVDSnap_SOURCES  = tstVDSnap.cpp
+ tstVDShareable_SOURCES = tstVDShareable.cpp
 endif
 
Index: /trunk/src/VBox/Devices/Storage/testcase/tstVDShareable.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/testcase/tstVDShareable.cpp	(revision 31193)
+++ /trunk/src/VBox/Devices/Storage/testcase/tstVDShareable.cpp	(revision 31193)
@@ -0,0 +1,179 @@
+/* $Id$ */
+/** @file
+ * Simple VBox HDD container test utility for shareable images.
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <VBox/VBoxHDD.h>
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <iprt/asm-amd64-x86.h>
+#include <iprt/dir.h>
+#include <iprt/string.h>
+#include <iprt/stream.h>
+#include <iprt/file.h>
+#include <iprt/mem.h>
+#include <iprt/initterm.h>
+#include <iprt/rand.h>
+#include "stdio.h"
+#include "stdlib.h"
+
+#define VHD_TEST
+#define VDI_TEST
+#define VMDK_TEST
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** The error count. */
+unsigned g_cErrors = 0;
+
+
+static void tstVDError(void *pvUser, int rc, RT_SRC_POS_DECL,
+                       const char *pszFormat, va_list va)
+{
+    g_cErrors++;
+    RTPrintf("tstVD: Error %Rrc at %s:%u (%s): ", rc, RT_SRC_POS_ARGS);
+    RTPrintfV(pszFormat, va);
+    RTPrintf("\n");
+}
+
+static int tstVDMessage(void *pvUser, const char *pszFormat, ...)
+{
+    va_list va;
+
+    RTPrintf("tstVD: ");
+    va_start(va, pszFormat);
+    RTPrintfV(pszFormat, va);
+    va_end(va);
+    return VINF_SUCCESS;
+}
+
+static int tstVDCreateShareDelete(const char *pszBackend, const char *pszFilename,
+                                  uint64_t cbSize, unsigned uFlags)
+{
+    int rc;
+    PVBOXHDD pVD = NULL, pVD2 = NULL;
+    PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
+    PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
+    PVDINTERFACE     pVDIfs = NULL;
+    VDINTERFACE      VDIError;
+    VDINTERFACEERROR VDIErrorCallbacks;
+
+#define CHECK(str) \
+    do \
+    { \
+        RTPrintf("%s rc=%Rrc\n", str, rc); \
+        if (RT_FAILURE(rc)) \
+        { \
+            VDDestroy(pVD); \
+            return rc; \
+        } \
+    } while (0)
+
+    /* Create error interface. */
+    VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
+    VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
+    VDIErrorCallbacks.pfnError = tstVDError;
+    VDIErrorCallbacks.pfnMessage = tstVDMessage;
+
+    rc = VDInterfaceAdd(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks,
+                        NULL, &pVDIfs);
+    AssertRC(rc);
+
+    rc = VDCreate(&VDIError, &pVD);
+    CHECK("VDCreate()");
+    rc = VDCreate(&VDIError, &pVD2);
+    CHECK("VDCreate() #2");
+
+    rc = VDCreateBase(pVD, pszBackend, pszFilename, cbSize,
+                      uFlags, "Test image", &PCHS, &LCHS, NULL,
+                      VD_OPEN_FLAGS_NORMAL, NULL, NULL);
+    CHECK("VDCreateBase()");
+
+    VDClose(pVD, false);
+
+    rc = VDOpen(pVD, pszBackend, pszFilename, VD_OPEN_FLAGS_SHAREABLE, NULL);
+    CHECK("VDOpen()");
+    rc = VDOpen(pVD2, pszBackend, pszFilename, VD_OPEN_FLAGS_SHAREABLE, NULL);
+    CHECK("VDOpen() #2");
+    if (VDIsReadOnly(pVD2))
+        rc = VERR_VD_IMAGE_READ_ONLY;
+
+    VDClose(pVD2, false);
+    VDClose(pVD, true);
+
+    VDDestroy(pVD);
+    VDDestroy(pVD2);
+#undef CHECK
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    RTR3Init();
+    int rc;
+
+    RTPrintf("tstVD: TESTING...\n");
+
+    /*
+     * Clean up potential leftovers from previous unsuccessful runs.
+     */
+    RTFileDelete("tmpVDCreate.vdi");
+
+    if (!RTDirExists("tmp"))
+    {
+        rc = RTDirCreate("tmp", RTFS_UNIX_IRWXU);
+        if (RT_FAILURE(rc))
+        {
+            RTPrintf("tstVD: Failed to create 'tmp' directory! rc=%Rrc\n", rc);
+            g_cErrors++;
+        }
+    }
+
+#ifdef VDI_TEST
+    rc = tstVDCreateShareDelete("VDI", "tmpVDCreate.vdi", 10 * _1M,
+                                VD_IMAGE_FLAGS_FIXED);
+    if (RT_FAILURE(rc))
+    {
+        RTPrintf("tstVD: VDI shareable test failed! rc=%Rrc\n", rc);
+        g_cErrors++;
+    }
+#endif /* VDI_TEST */
+
+    /*
+     * Clean up any leftovers.
+     */
+    RTFileDelete("tmpVDCreate.vdi");
+
+    rc = VDShutdown();
+    if (RT_FAILURE(rc))
+    {
+        RTPrintf("tstVD: unloading backends failed! rc=%Rrc\n", rc);
+        g_cErrors++;
+    }
+     /*
+      * Summary
+      */
+    if (!g_cErrors)
+        RTPrintf("tstVD: SUCCESS\n");
+    else
+        RTPrintf("tstVD: FAILURE - %d errors\n", g_cErrors);
+
+    return !!g_cErrors;
+}
+
