diff --git a/config/autoconf.mk.in b/config/autoconf.mk.in index 36d0613b0674..d1b412ace07e 100644 --- a/config/autoconf.mk.in +++ b/config/autoconf.mk.in @@ -104,7 +104,8 @@ MOZ_EXTENSIONS = @MOZ_EXTENSIONS@ MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@ MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@ MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@ -MOZ_IPC = @MOZ_IPC@ +MOZ_IPC = @MOZ_IPC@ +MOZ_IPDL_TESTS = @MOZ_IPDL_TESTS@ MOZ_LEAKY = @MOZ_LEAKY@ MOZ_MEMORY = @MOZ_MEMORY@ MOZ_JPROF = @MOZ_JPROF@ diff --git a/configure.in b/configure.in index cd75a18f3fa6..80354850523a 100644 --- a/configure.in +++ b/configure.in @@ -5243,6 +5243,26 @@ fi AC_SUBST(MOZ_IPC) +dnl ======================================================== +dnl = Enable IPDL's "expensive" unit tests +dnl ======================================================== +MOZ_IPDL_TESTS= + +MOZ_ARG_ENABLE_BOOL(ipdl-tests, +[ --enable-ipdl-tests Enable expensive IPDL tests], + MOZ_IPDL_TESTS=1, + MOZ_IPDL_TESTS=) + +if test -z "$MOZ_IPC" -a -n "$MOZ_IPDL_TESTS"; then + AC_MSG_ERROR([--enable-ipdl-tests requires --enable-ipc]) +fi + +if test -n "$MOZ_IPDL_TESTS"; then + AC_DEFINE(MOZ_IPDL_TESTS) +fi + +AC_SUBST(MOZ_IPDL_TESTS) + dnl ======================================================== dnl = Disable plugin support dnl ======================================================== diff --git a/ipc/ipdl/Makefile.in b/ipc/ipdl/Makefile.in index 397472892db9..265b0d1bb972 100644 --- a/ipc/ipdl/Makefile.in +++ b/ipc/ipdl/Makefile.in @@ -40,18 +40,16 @@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk - -DIRS += test - include $(topsrcdir)/config/rules.mk -IPDLDIRS = \ - dom/plugins \ - dom/ipc \ - netwerk/ipc \ - netwerk/protocol/http/src \ - ipc/test-harness \ - ipc/testshell \ +IPDLDIRS = \ + dom/plugins \ + dom/ipc \ + netwerk/ipc \ + netwerk/protocol/http/src \ + ipc/ipdl/test/cxx \ + ipc/test-harness \ + ipc/testshell \ $(NULL) vpath %.ipdl $(topsrcdir) diff --git a/ipc/ipdl/test/Makefile.in b/ipc/ipdl/test/Makefile.in index a0fdd4ded0e6..199ddaee5d24 100644 --- a/ipc/ipdl/test/Makefile.in +++ b/ipc/ipdl/test/Makefile.in @@ -41,6 +41,12 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS += ipdl cxx +# we ignore MOZ_IPDL_TESTS for the IPDL-compiler-only tests, since they're +# quick and painless +DIRS += ipdl + +ifdef MOZ_IPDL_TESTS +DIRS += cxx +endif include $(topsrcdir)/config/rules.mk diff --git a/ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.cpp b/ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.cpp new file mode 100644 index 000000000000..68a77ea18783 --- /dev/null +++ b/ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.cpp @@ -0,0 +1,56 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPDL Test Harness. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones . + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "IPDLUnitTestSubprocess.h" + +using mozilla::ipc::GeckoChildProcessHost; + +namespace mozilla { +namespace _ipdltest { + +IPDLUnitTestSubprocess::IPDLUnitTestSubprocess() : + GeckoChildProcessHost(GeckoProcessType_IPDLUnitTest) +{ +} + +IPDLUnitTestSubprocess::~IPDLUnitTestSubprocess() +{ +} + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.h b/ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.h new file mode 100644 index 000000000000..5eb72f5ac92e --- /dev/null +++ b/ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.h @@ -0,0 +1,70 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPDL Test Harness. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones . + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozilla__ipdltest_IPDLUnitTestTestSubprocess_h +#define mozilla__ipdltest_IPDLUnitTestTestSubprocess_h 1 + + +#include "mozilla/ipc/GeckoChildProcessHost.h" + +namespace mozilla { +namespace _ipdltest { +//----------------------------------------------------------------------------- + +class IPDLUnitTestSubprocess : public mozilla::ipc::GeckoChildProcessHost +{ +public: + IPDLUnitTestSubprocess(); + ~IPDLUnitTestSubprocess(); + + /** + * Asynchronously launch the plugin process. + */ + // Could override parent Launch, but don't need to here + //bool Launch(); + +private: + DISALLOW_EVIL_CONSTRUCTORS(IPDLUnitTestSubprocess); +}; + + +} // namespace _ipdltest +} // namespace mozilla + + +#endif // ifndef mozilla__ipdltest_IPDLUnitTestTestSubprocess_h diff --git a/ipc/ipdl/test/cxx/IPDLUnitTestThreadChild.cpp b/ipc/ipdl/test/cxx/IPDLUnitTestThreadChild.cpp new file mode 100644 index 000000000000..98f9d17f0b70 --- /dev/null +++ b/ipc/ipdl/test/cxx/IPDLUnitTestThreadChild.cpp @@ -0,0 +1,72 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones . + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "IPDLUnitTestThreadChild.h" + +#include "IPDLUnitTests.h" + +using mozilla::ipc::GeckoThread; + +namespace mozilla { +namespace _ipdltest { + +IPDLUnitTestThreadChild::IPDLUnitTestThreadChild() : + GeckoThread() +{ +} + +IPDLUnitTestThreadChild::~IPDLUnitTestThreadChild() +{ +} + +void +IPDLUnitTestThreadChild::Init() +{ + GeckoThread::Init(); + IPDLUnitTestChildInit(channel(), owner_loop()); +} + +void +IPDLUnitTestThreadChild::CleanUp() +{ + GeckoThread::CleanUp(); + IPDLUnitTestChildCleanUp(); +} + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/cxx/IPDLUnitTestThreadChild.h b/ipc/ipdl/test/cxx/IPDLUnitTestThreadChild.h new file mode 100644 index 000000000000..d5debe3edaa8 --- /dev/null +++ b/ipc/ipdl/test/cxx/IPDLUnitTestThreadChild.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones . + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozilla__ipdltest_IPDLUnitTestThreadChild_h +#define mozilla__ipdltest_IPDLUnitTestThreadChild_h 1 + +#include "mozilla/ipc/GeckoThread.h" + +namespace mozilla { +namespace _ipdltest { + +class IPDLUnitTestThreadChild : public mozilla::ipc::GeckoThread +{ +public: + IPDLUnitTestThreadChild(); + ~IPDLUnitTestThreadChild(); + +protected: + virtual void Init(); + virtual void CleanUp(); +}; + +} // namespace _ipdltest +} // namespace mozilla + +#endif // ifndef mozilla__ipdltest_IPDLUnitTestThreadChild_h diff --git a/ipc/ipdl/test/cxx/IPDLUnitTests.h b/ipc/ipdl/test/cxx/IPDLUnitTests.h new file mode 100644 index 000000000000..68952de2bcc5 --- /dev/null +++ b/ipc/ipdl/test/cxx/IPDLUnitTests.h @@ -0,0 +1,93 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Jones . + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozilla__ipdltest_IPDLUnitTests_h +#define mozilla__ipdltest_IPDLUnitTests_h 1 + +#include "base/message_loop.h" +#include "chrome/common/ipc_channel.h" + + +#define MOZ_IPDL_TESTFAIL_LABEL "TEST-UNEXPECTED-FAIL" +#define MOZ_IPDL_TESTPASS_LABEL "TEST-PASS" + +// NB: these are named like the similar functions in +// xpcom/test/TestHarness.h. The names should nominally be kept in +// sync. + +#define fail(fmt, ...) \ + do { \ + fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL " | %s | " fmt "\n", \ + IPDLUnitTestName(), ## __VA_ARGS__); \ + NS_RUNTIMEABORT("failed test"); \ + } while (0) + +#define passed(fmt, ...) \ + fprintf(stderr, MOZ_IPDL_TESTPASS_LABEL " | %s | " fmt "\n", \ + IPDLUnitTestName(), ## __VA_ARGS__) + + +namespace mozilla { +namespace _ipdltest { + + +//----------------------------------------------------------------------------- +// both processes +const char* const IPDLUnitTestName(); + + +//----------------------------------------------------------------------------- +// parent process only + +void IPDLUnitTestMain(void* aData); + +// TODO: could clean up parent actor/subprocess + + +//----------------------------------------------------------------------------- +// child process only + +void IPDLUnitTestChildInit(IPC::Channel* transport, MessageLoop* worker); +void IPDLUnitTestChildCleanUp(); + + +} // namespace _ipdltest +} // namespace mozilla + + +#endif // ifndef mozilla__ipdltest_IPDLUnitTests_h diff --git a/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp new file mode 100644 index 000000000000..e49058a20d17 --- /dev/null +++ b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp @@ -0,0 +1,198 @@ +// +// Autogenerated from Python template. Hands off. +// + +#include "IPDLUnitTests.h" + +#include + +#include "base/command_line.h" +#include "base/string_util.h" + +#include "IPDLUnitTestSubprocess.h" +#include "IPDLUnitTestThreadChild.h" + +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${INCLUDES} +//----------------------------------------------------------------------------- + +using mozilla::_ipdltest::IPDLUnitTestSubprocess; +using mozilla::_ipdltest::IPDLUnitTestThreadChild; + +//----------------------------------------------------------------------------- +// data/functions accessed by both parent and child processes + +namespace { +char* gIPDLUnitTestName = NULL; // "leaks" +} + + +namespace mozilla { +namespace _ipdltest { + +const char* const +IPDLUnitTestName() +{ + if (!gIPDLUnitTestName) { + std::vector args = + CommandLine::ForCurrentProcess()->GetLooseValues(); + gIPDLUnitTestName = strdup(WideToUTF8(args[args.size()-1]).c_str()); + } + return gIPDLUnitTestName; +} + +} // namespace _ipdltest +} // namespace mozilla + + +namespace { + +enum IPDLUnitTestType { + NoneTest = 0, + +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${ENUM_VALUES} + + LastTest = ${LAST_ENUM} +//----------------------------------------------------------------------------- +}; + + +IPDLUnitTestType +IPDLUnitTestFromString(const char* const aString) +{ + if (!aString) + return static_cast(0); +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${STRING_TO_ENUMS} +//----------------------------------------------------------------------------- + else + return static_cast(0); +} + + +const char* const +IPDLUnitTestToString(IPDLUnitTestType aTest) +{ + switch (aTest) { +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${ENUM_TO_STRINGS} +//----------------------------------------------------------------------------- + + default: + return NULL; + } +} + + +IPDLUnitTestType +IPDLUnitTest() +{ + return IPDLUnitTestFromString(mozilla::_ipdltest::IPDLUnitTestName()); +} + + +} // namespace + + +//----------------------------------------------------------------------------- +// parent process only + +namespace { +void* gParentActor = NULL; +} + + +namespace mozilla { +namespace _ipdltest { + +void +IPDLUnitTestMain(void* aData) +{ + char* testString = reinterpret_cast(aData); + IPDLUnitTestType test = IPDLUnitTestFromString(testString); + if (!test) { + // use this instead of |fail()| because we don't know what the test is + fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\\n", + "<--->", testString); + NS_RUNTIMEABORT("can't continue"); + } + gIPDLUnitTestName = testString; + + std::wstring testWString = UTF8ToWide(testString); + std::vector testCaseArgs; + testCaseArgs.push_back(testWString); + + IPDLUnitTestSubprocess* subprocess = new IPDLUnitTestSubprocess(); + if (!subprocess->SyncLaunch(testCaseArgs)) + fail("problem launching subprocess"); + + IPC::Channel* transport = subprocess->GetChannel(); + if (!transport) + fail("no transport"); + + switch (test) { +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${PARENT_MAIN_CASES} +//----------------------------------------------------------------------------- + + default: + fail("not reached"); + return; // unreached + } +} + +} // namespace _ipdltest +} // namespace mozilla + + +//----------------------------------------------------------------------------- +// child process only + +namespace { +void* gChildActor = NULL; +} + + +namespace mozilla { +namespace _ipdltest { + +void +IPDLUnitTestChildInit(IPC::Channel* transport, MessageLoop* worker) +{ + switch (IPDLUnitTest()) { +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${CHILD_INIT_CASES} +//----------------------------------------------------------------------------- + + default: + fail("not reached"); + return; // unreached + } +} + +void IPDLUnitTestChildCleanUp() +{ + if (!gChildActor) + return; + + switch (IPDLUnitTest()) { +//----------------------------------------------------------------------------- +//===== TEMPLATED ===== +${CHILD_CLEANUP_CASES} +//----------------------------------------------------------------------------- + + default: + fail("not reached"); + return; // unreached + } +} + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/cxx/Makefile.in b/ipc/ipdl/test/cxx/Makefile.in index ae166af86387..2d573a0d42fd 100644 --- a/ipc/ipdl/test/cxx/Makefile.in +++ b/ipc/ipdl/test/cxx/Makefile.in @@ -40,8 +40,54 @@ srcdir = @srcdir@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk + +TOOL_DIRS += app + +MODULE = ipdlunittest + +EXPORTS_NAMESPACES = mozilla/_ipdltest +EXPORTS_mozilla/_ipdltest = \ + IPDLUnitTests.h \ + IPDLUnitTestThreadChild.h \ + $(NULL) + +LIBRARY_NAME = $(MODULE)_s +LIBXUL_LIBRARY = 1 +FORCE_STATIC_LIB = 1 +EXPORT_LIBRARY = 1 + + +IPDLTESTS = \ + TestSanity \ + $(NULL) + +IPDLTESTSRCS = $(addsuffix .cpp,$(IPDLTESTS)) +IPDLTESTHDRS = $(addprefix $(srcdir)/,$(addsuffix .h,$(IPDLTESTS))) + +TESTER_TEMPLATE := $(srcdir)/IPDLUnitTests.template.cpp +GENTESTER := $(srcdir)/genIPDLUnitTests.py + +CPPSRCS = \ + IPDLUnitTests.cpp \ + IPDLUnitTestSubprocess.cpp \ + IPDLUnitTestThreadChild.cpp \ + $(IPDLTESTSRCS) \ + $(NULL) + + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk +RUNIPDLTEST := $(RUN_TEST_PROGRAM) $(DEPTH)/dist/bin/ipdlunittest$(BIN_SUFFIX) + + +IPDLUnitTests.cpp : $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS) + $(PYTHON) $< $(TESTER_TEMPLATE) $(IPDLTESTS) > $@ + check:: - echo "TODO: C++/IPDL unit tests" + @$(EXIT_ON_ERROR) \ + for test in $(IPDLTESTS); do \ + $(RUNIPDLTEST) $$test ; \ + done diff --git a/ipc/ipdl/test/cxx/PTestSanity.ipdl b/ipc/ipdl/test/cxx/PTestSanity.ipdl new file mode 100644 index 000000000000..c8b6a9af1a82 --- /dev/null +++ b/ipc/ipdl/test/cxx/PTestSanity.ipdl @@ -0,0 +1,31 @@ + +namespace mozilla { +namespace _ipdltest { + + +protocol PTestSanity { + +child: + Ping(int zero); + +parent: + Pong(int one); + +both: + UNREACHED(); + + +state PING: + send Ping goto PONG; + +state PONG: + recv Pong goto DEAD; + + // hmm ... maybe support this idiom natively? +state DEAD: + send UNREACHED goto DEAD; +}; + + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/cxx/README.txt b/ipc/ipdl/test/cxx/README.txt new file mode 100644 index 000000000000..9e4cf6647604 --- /dev/null +++ b/ipc/ipdl/test/cxx/README.txt @@ -0,0 +1,47 @@ +To add a new IPDL C++ unit test, you need to create (at least) the +following files (for a test "TestFoo"): + + - PTestFoo.ipdl, specifying the top-level protocol used for the test + + - TestFoo.h, declaring the top-level parent/child actors used for + the test + + - TestFoo.cpp, defining the top-level actors + +Next + + - add PTestFoo.ipdl to ipdl.mk + + - append TestFoo to the variable IPDLTESTS in Makefile.in + +The IPDL test harness will try to execute |testFooParentActor->Main()| +to kick off your test. Make sure you define |TestFooParent::Main()|. + +If your test passes its criteria, please call +|MOZ_IPDL_TESTPASS("msg")| and "exit gracefully". + +If your tests fails, please call |MOZ_IPDL_TESTFAIL("msg")| and "exit +ungracefully", preferably by abort()ing. + + +If all goes well, running + + make -C $OBJDIR/ipc/ipdl/test/cxx + +will update the file IPDLUnitTests.cpp (the test launcher), and your +new code will be built automatically. + + +You can launch your new test by invoking + + make -C $OBJDIR/ipc/ipdl/test/cxx check + +If you want to launch only your test, run + + cd $OBJDIR/dist/bin + ./run-mozilla.sh ./ipdlunittest TestFoo + + +For a bare-bones example of adding a test, take a look at +PTestSanity.ipdl, TestSanity.h, TestSanity.cpp, and how "TestSanity" +is included in ipdl.mk and Makefile.in. diff --git a/ipc/ipdl/test/cxx/TestSanity.cpp b/ipc/ipdl/test/cxx/TestSanity.cpp new file mode 100644 index 000000000000..a6821906c096 --- /dev/null +++ b/ipc/ipdl/test/cxx/TestSanity.cpp @@ -0,0 +1,91 @@ +#include "TestSanity.h" + +#include "nsIAppShell.h" + +#include "nsCOMPtr.h" +#include "nsServiceManagerUtils.h" // do_GetService() +#include "nsWidgetsCID.h" // NS_APPSHELL_CID + +#include "IPDLUnitTests.h" // fail etc. + +namespace mozilla { +namespace _ipdltest { + +//----------------------------------------------------------------------------- +// parent + +TestSanityParent::TestSanityParent() +{ + MOZ_COUNT_CTOR(TestSanityParent); +} + +TestSanityParent::~TestSanityParent() +{ + MOZ_COUNT_DTOR(TestSanityParent); +} + +void +TestSanityParent::Main() +{ + if (!SendPing(0)) + fail("sending Ping"); +} + + +bool +TestSanityParent::RecvPong(const int& one) +{ + if (1 != one) + fail("invalid argument `%d', should have been `1'", one); + + passed("sent ping/received pong"); + + static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + nsCOMPtr appShell (do_GetService(kAppShellCID)); + appShell->Exit(); + + return true; +} + +bool +TestSanityParent::RecvUNREACHED() +{ + fail("unreached"); + return false; // not reached +} + + +//----------------------------------------------------------------------------- +// child + +TestSanityChild::TestSanityChild() +{ + MOZ_COUNT_CTOR(TestSanityChild); +} + +TestSanityChild::~TestSanityChild() +{ + MOZ_COUNT_DTOR(TestSanityChild); +} + +bool +TestSanityChild::RecvPing(const int& zero) +{ + if (0 != zero) + fail("invalid argument `%d', should have been `0'", zero); + + if (!SendPong(1)) + fail("sending Pong"); + return true; +} + +bool +TestSanityChild::RecvUNREACHED() +{ + fail("unreached"); + return false; // not reached +} + + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/cxx/TestSanity.h b/ipc/ipdl/test/cxx/TestSanity.h new file mode 100644 index 000000000000..7dc871e0cafb --- /dev/null +++ b/ipc/ipdl/test/cxx/TestSanity.h @@ -0,0 +1,44 @@ +#ifndef mozilla__ipdltest_TestSanity_h +#define mozilla__ipdltest_TestSanity_h 1 + + +#include "mozilla/_ipdltest/PTestSanityParent.h" +#include "mozilla/_ipdltest/PTestSanityChild.h" + +namespace mozilla { +namespace _ipdltest { + + +class TestSanityParent : + public PTestSanityParent +{ +public: + TestSanityParent(); + virtual ~TestSanityParent(); + + void Main(); + +protected: + virtual bool RecvPong(const int& one); + virtual bool RecvUNREACHED(); +}; + + +class TestSanityChild : + public PTestSanityChild +{ +public: + TestSanityChild(); + virtual ~TestSanityChild(); + +protected: + virtual bool RecvPing(const int& zero); + virtual bool RecvUNREACHED(); +}; + + +} // namespace _ipdltest +} // namespace mozilla + + +#endif // ifndef mozilla__ipdltest_TestSanity_h diff --git a/ipc/ipdl/test/cxx/app/Makefile.in b/ipc/ipdl/test/cxx/app/Makefile.in new file mode 100644 index 000000000000..37bc73fe3570 --- /dev/null +++ b/ipc/ipdl/test/cxx/app/Makefile.in @@ -0,0 +1,72 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla IPC. +# +# The Initial Developer of the Original Code is +# The Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = ipdlunittest +PROGRAM = $(MODULE)$(BIN_SUFFIX) +ENABLE_CXX_EXCEPTIONS = 1 + +LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre + +CPPSRCS = \ + TestIPDL.cpp \ + $(NULL) + +LIBS = \ + $(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \ + $(LIBXUL_LIBS) \ + $(MOZ_JS_LIBS) \ + $(NSPR_LIBS) \ + $(NULL) + +include $(topsrcdir)/config/config.mk + +ifdef _MSC_VER +ifdef WINCE +WIN32_EXE_LDFLAGS += -ENTRY:mainWCRTStartup +else +WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup +endif +endif + +include $(topsrcdir)/ipc/chromium/chromium-config.mk +include $(topsrcdir)/config/rules.mk diff --git a/ipc/ipdl/test/cxx/app/TestIPDL.cpp b/ipc/ipdl/test/cxx/app/TestIPDL.cpp new file mode 100644 index 000000000000..0641d59bf656 --- /dev/null +++ b/ipc/ipdl/test/cxx/app/TestIPDL.cpp @@ -0,0 +1,52 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla IPC. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsXULAppAPI.h" + +#if defined(XP_WIN) +#include +#include "nsWindowsWMain.cpp" +#endif + +int +main(int argc, char** argv) +{ + // the first argument specifies which IPDL test case/suite to load + if (argc < 2) + return 1; + + return XRE_RunIPDLTest(argc, argv); +} diff --git a/ipc/ipdl/test/cxx/genIPDLUnitTests.py b/ipc/ipdl/test/cxx/genIPDLUnitTests.py new file mode 100644 index 000000000000..cf7768ea2a86 --- /dev/null +++ b/ipc/ipdl/test/cxx/genIPDLUnitTests.py @@ -0,0 +1,107 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is Mozilla Firefox. +# +# The Initial Developer of the Original Code is +# The Mozilla Foundation . +# Portions created by the Initial Developer are Copyright (C) 2009 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Chris Jones +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +import string, sys + +def main(argv): + template = argv[1] + unittests = argv[2:] + + includes = '\n'.join([ + '#include "%s.h"'% (t) for t in unittests ]) + + + enum_values = '\n'.join([ + ' %s,'% (t) for t in unittests ]) + last_enum = unittests[-1] + + + string_to_enums = '\n'.join([ + ''' else if (!strcmp(aString, "%s")) + return %s;'''% (t, t) for t in unittests ]) + + enum_to_strings = '\n'.join([ + ''' case %s: + return "%s";'''%(t, t) for t in unittests ]) + + + parent_main_cases = '\n'.join([ +''' case %s: { + %sParent** parent = + reinterpret_cast<%sParent**>(&gParentActor); + *parent = new %sParent(); + (*parent)->Open(transport); + return (*parent)->Main(); + } +'''% (t, t, t, t) for t in unittests ]) + + + child_init_cases = '\n'.join([ +''' case %s: { + %sChild** child = + reinterpret_cast<%sChild**>(&gChildActor); + *child = new %sChild(); + (*child)->Open(transport, worker); + return; + } +'''% (t, t, t, t) for t in unittests ]) + + child_cleanup_cases = '\n'.join([ +''' case %s: { + %sChild** child = + reinterpret_cast<%sChild**>(&gChildActor); + delete *child; + *child = 0; + return; + } +'''% (t, t, t) for t in unittests ]) + + + templatefile = open(template, 'r') + sys.stdout.write( + string.Template(templatefile.read()).substitute( + INCLUDES=includes, + ENUM_VALUES=enum_values, LAST_ENUM=last_enum, + STRING_TO_ENUMS=string_to_enums, + ENUM_TO_STRINGS=enum_to_strings, + PARENT_MAIN_CASES=parent_main_cases, + CHILD_INIT_CASES=child_init_cases, + CHILD_CLEANUP_CASES=child_cleanup_cases)) + templatefile.close() + +if __name__ == '__main__': + main(sys.argv) diff --git a/ipc/ipdl/test/cxx/ipdl.mk b/ipc/ipdl/test/cxx/ipdl.mk new file mode 100644 index 000000000000..9948cfbbd1ed --- /dev/null +++ b/ipc/ipdl/test/cxx/ipdl.mk @@ -0,0 +1,3 @@ +IPDLSRCS = \ + PTestSanity.ipdl \ + $(NULL) diff --git a/ipc/ipdl/test/ipdl/Makefile.in b/ipc/ipdl/test/ipdl/Makefile.in index 8577701338bb..8d9d2bdc5705 100644 --- a/ipc/ipdl/test/ipdl/Makefile.in +++ b/ipc/ipdl/test/ipdl/Makefile.in @@ -46,10 +46,10 @@ OKTESTS := $(wildcard $(srcdir)/ok/*.ipdl) ERRORTESTS := $(wildcard $(srcdir)/error/*.ipdl) check:: - @$(PYTHON) $(srcdir)/runtests.py \ - $(srcdir)/ok $(srcdir)/error \ - $(PYTHON) $(topsrcdir)/config/pythonpath.py \ - -I$(topsrcdir)/other-licenses/ply \ - $(topsrcdir)/ipc/ipdl/ipdl.py \ - OKTESTS $(OKTESTS) \ + @$(PYTHON) $(srcdir)/runtests.py \ + $(srcdir)/ok $(srcdir)/error \ + $(PYTHON) $(topsrcdir)/config/pythonpath.py \ + -I$(topsrcdir)/other-licenses/ply \ + $(topsrcdir)/ipc/ipdl/ipdl.py \ + OKTESTS $(OKTESTS) \ ERRORTESTS $(ERRORTESTS) diff --git a/toolkit/library/libxul-config.mk b/toolkit/library/libxul-config.mk index 36442bd240c0..f1fbdcac26d4 100644 --- a/toolkit/library/libxul-config.mk +++ b/toolkit/library/libxul-config.mk @@ -101,6 +101,10 @@ STATIC_LIBS += \ ipctestharness_s \ $(NULL) +ifdef MOZ_IPDL_TESTS +STATIC_LIBS += ipdlunittest_s +endif + ifeq (Linux,$(OS_ARCH)) OS_LIBS += -lrt endif diff --git a/toolkit/toolkit-tiers.mk b/toolkit/toolkit-tiers.mk index de58bcb6eb69..88d3a1637335 100644 --- a/toolkit/toolkit-tiers.mk +++ b/toolkit/toolkit-tiers.mk @@ -170,6 +170,10 @@ ifdef ACCESSIBILITY tier_gecko_dirs += accessible endif +ifdef MOZ_IPDL_TESTS +tier_gecko_dirs += ipc/ipdl/test +endif + # # tier "toolkit" - xpfe & toolkit # diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 8b288b4a0426..0ffc053b9f01 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -727,9 +727,10 @@ SYNC_ENUMS(DEFAULT, Default) SYNC_ENUMS(PLUGIN, Plugin) SYNC_ENUMS(CONTENT, Content) SYNC_ENUMS(TESTHARNESS, TestHarness) +SYNC_ENUMS(IPDLUNITTEST, IPDLUnitTest) // .. and ensure that that is all of them: -PR_STATIC_ASSERT(GeckoProcessType_TestHarness + 1 == GeckoProcessType_End); +PR_STATIC_ASSERT(GeckoProcessType_IPDLUnitTest + 1 == GeckoProcessType_End); NS_IMETHODIMP nsXULAppInfo::GetProcessType(PRUint32* aResult) diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index 84a704abbc5f..f906ece93c37 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -83,6 +83,13 @@ #include "mozilla/test/TestThreadChild.h" #include "mozilla/Monitor.h" +#ifdef MOZ_IPDL_TESTS +#include "mozilla/_ipdltest/IPDLUnitTests.h" +#include "mozilla/_ipdltest/IPDLUnitTestThreadChild.h" + +using mozilla::_ipdltest::IPDLUnitTestThreadChild; +#endif // ifdef MOZ_IPDL_TESTS + using mozilla::ipc::GeckoChildProcessHost; using mozilla::ipc::GeckoThread; using mozilla::ipc::BrowserProcessSubThread; @@ -283,6 +290,14 @@ XRE_InitChildProcess(int aArgc, mainThread = new TestThreadChild(); break; + case GeckoProcessType_IPDLUnitTest: +#ifdef MOZ_IPDL_TESTS + mainThread = new IPDLUnitTestThreadChild(); +#else + NS_RUNTIMEABORT("rebuild with --enable-ipdl-tests"); +#endif + break; + default: NS_RUNTIMEABORT("Unknown main thread class"); } @@ -410,6 +425,29 @@ XRE_RunIPCTestHarness(int aArgc, char* aArgv[]) return 0; } +#ifdef MOZ_IPDL_TESTS +//----------------------------------------------------------------------------- +// IPDL unit test + +int +XRE_RunIPDLTest(int aArgc, char** aArgv) +{ + if (aArgc < 2) { + fprintf(stderr, "TEST-UNEXPECTED-FAIL | <---> | insufficient #args, need at least 2\n"); + return 1; + } + + void* data = reinterpret_cast(aArgv[aArgc-1]); + + nsresult rv = + XRE_InitParentProcess( + --aArgc, aArgv, mozilla::_ipdltest::IPDLUnitTestMain, data); + NS_ENSURE_SUCCESS(rv, 1); + + return 0; +} +#endif // ifdef MOZ_IPDL_TESTS + nsresult XRE_RunAppShell() { diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index 7b7d64ca2583..c7fabc3e02c6 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -426,6 +426,7 @@ enum GeckoProcessType { GeckoProcessType_Content, GeckoProcessType_TestHarness, + GeckoProcessType_IPDLUnitTest, GeckoProcessType_End, GeckoProcessType_Invalid = GeckoProcessType_End @@ -436,6 +437,7 @@ static const char* const kGeckoProcessTypeString[] = { "plugin", "tab", "testharness", + "ipdlunittest" }; PR_STATIC_ASSERT(sizeof(kGeckoProcessTypeString) / @@ -469,6 +471,10 @@ XRE_API(int, XRE_RunIPCTestHarness, (int aArgc, char* aArgv[])) +XRE_API(int, + XRE_RunIPDLTest, (int aArgc, + char* aArgv[])) + XRE_API(nsresult, XRE_RunAppShell, ()) diff --git a/xpcom/system/nsIXULRuntime.idl b/xpcom/system/nsIXULRuntime.idl index b8f2769c6810..ae3e8f32f451 100644 --- a/xpcom/system/nsIXULRuntime.idl +++ b/xpcom/system/nsIXULRuntime.idl @@ -94,6 +94,7 @@ interface nsIXULRuntime : nsISupports const unsigned long PROCESS_TYPE_PLUGIN = 1; const unsigned long PROCESS_TYPE_CONTENT = 2; const unsigned long PROCESS_TYPE_TESTHARNESS = 3; + const unsigned long PROCESS_TYPE_IPDLUNITTEST = 4; /** * The type of the caller's process. Returns one of the values above.