diff --git a/dune/solvers/test/CMakeLists.txt b/dune/solvers/test/CMakeLists.txt
index 67e45116457deccf080d10f06463b36a69674b58..22af482060e8142dc5fdf954eea7d63260a6b63f 100644
--- a/dune/solvers/test/CMakeLists.txt
+++ b/dune/solvers/test/CMakeLists.txt
@@ -8,6 +8,7 @@ dune_add_test(SOURCES genericvectortoolstest.cc)
 dune_add_test(SOURCES lowrankoperatortest.cc)
 dune_add_test(SOURCES nulloperatortest.cc)
 dune_add_test(SOURCES sumoperatortest.cc)
+dune_add_test(SOURCES wrapownsharetest.cc)
 
 if(HAVE_IPOPT)
     dune_add_test(SOURCES quadraticipoptsolvertest.cc)
diff --git a/dune/solvers/test/wrapownsharetest.cc b/dune/solvers/test/wrapownsharetest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6763153ef3aa7590063ddcac0abdac4eec0acc93
--- /dev/null
+++ b/dune/solvers/test/wrapownsharetest.cc
@@ -0,0 +1,138 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#include <config.h>
+
+#include <iostream>
+#include <sstream>
+#include <memory>
+
+#include <dune/solvers/common/wrapownshare.hh>
+
+class Foo
+{
+public:
+  Foo(std::size_t counter) :
+      counter_(counter)
+  {}
+
+  Foo() :
+      counter_(0)
+  {}
+
+  Foo(Foo&& other) :
+      counter_(other.counter())
+  { std::cout << "move" << std::endl; }
+
+  Foo(const Foo& other) :
+      counter_(other.counter()+1)
+  { std::cout << "copy" << std::endl; }
+
+  std::size_t counter() const
+  { return counter_; }
+
+  virtual std::string name() const
+  { return "Foo"; }
+
+  virtual std::string str() const
+  {
+    std::stringstream s;
+    s << name() << ":" << counter();
+    return s.str();
+  }
+
+protected:
+  std::size_t counter_;
+};
+
+
+class Bar : public Foo
+{
+public:
+  using Foo::Foo;
+
+  virtual std::string name() const
+  {
+    return "Bar";
+  }
+};
+
+template<class Impl>
+bool doTests()
+{
+  // wrap non-const Impl&
+  {
+    Impl foo(0);
+    auto foo_p = Dune::Solvers::wrap_own_share<Foo>(foo);
+    std::cout << foo.str() << "   " << foo_p->str() << std::endl;
+    if (foo.counter() != foo_p->counter())
+      return false;
+  }
+
+  // wrap const Foo&
+  {
+    const Impl foo(0);
+    auto foo_p = Dune::Solvers::wrap_own_share<const Foo>(foo);
+    std::cout << foo.str() << "   " << foo_p->str() << std::endl;
+    if (foo.counter() != foo_p->counter())
+      return false;
+  }
+
+  // own Foo&& as Foo
+  {
+    auto foo_p = Dune::Solvers::wrap_own_share<Foo>(Impl());
+    std::cout << foo_p->str() << std::endl;
+    if (foo_p->counter() != std::size_t(0))
+      return false;
+  }
+
+  // own Foo&& as const Foo
+  {
+    auto foo_p = Dune::Solvers::wrap_own_share<const Foo>(Impl());
+    std::cout << foo_p->str() << std::endl;
+    if (foo_p->counter() != std::size_t(0))
+      return false;
+  }
+
+  // share shared_ptr to Foo as Foo
+  {
+    auto foo = std::make_shared<Impl>();
+    auto foo_p = Dune::Solvers::wrap_own_share<Foo>(foo);
+    std::cout << foo->str() << "   " << foo_p->str() << std::endl;
+    if (foo->counter() != foo_p->counter())
+      return false;
+  }
+
+  // share shared_ptr to Foo as const Foo
+  {
+    auto foo = std::make_shared<Impl>();
+    auto foo_p = Dune::Solvers::wrap_own_share<const Foo>(foo);
+    std::cout << foo->str() << "   " << foo_p->str() << std::endl;
+    if (foo->counter() != foo_p->counter())
+      return false;
+  }
+
+  // share shared_ptr to const Foo as const Foo
+  {
+    auto foo = std::make_shared<const Impl>();
+    auto foo_p = Dune::Solvers::wrap_own_share<const Foo>(foo);
+    std::cout << foo->str() << "   " << foo_p->str() << std::endl;
+    if (foo->counter() != foo_p->counter())
+      return false;
+  }
+
+  return true;
+}
+
+int main()
+{
+  std::cout << "Testing with Foo" << std::endl;
+  bool successful = doTests<Foo>();
+
+  std::cout << "Testing with Bar" << std::endl;
+  successful &= doTests<Bar>();
+
+  return !successful;
+}
+
+