diff --git a/dune/matrix-vector/test/CMakeLists.txt b/dune/matrix-vector/test/CMakeLists.txt
index ab5d8968bb8072bf3a64118f9ed22ac91fd8431b..ff2014510d0732066fea5e2d69018bd6e0eab2e1 100644
--- a/dune/matrix-vector/test/CMakeLists.txt
+++ b/dune/matrix-vector/test/CMakeLists.txt
@@ -1,2 +1,3 @@
 dune_add_test(SOURCES arithmetictest.cc)
 dune_add_test(SOURCES staticmatrixtoolstest.cc)
+dune_add_test(SOURCES triangularsolvetest.cc)
diff --git a/dune/matrix-vector/test/triangularsolvetest.cc b/dune/matrix-vector/test/triangularsolvetest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..28dd6857e33eaf925375b465787e6f4fd24a5a82
--- /dev/null
+++ b/dune/matrix-vector/test/triangularsolvetest.cc
@@ -0,0 +1,78 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#undef NDEBUG
+
+#include <dune/common/bitsetvector.hh>
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
+#include <dune/istl/bcrsmatrix.hh>
+#include <dune/istl/bvector.hh>
+#include <dune/istl/matrixindexset.hh>
+
+#include "../triangularsolve.hh"
+
+#include "common.hh"
+
+double const tol = 1e-10;
+
+template <int n, bool lower>
+bool test() {
+  bool passed = true;
+  Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>> M;
+  Dune::MatrixIndexSet indices(n, n);
+  for (size_t i = 0; i < n; ++i)
+    for (size_t j = lower ? 0 : i; j < (lower ? i + 1 : n); ++j)
+      indices.add(i, j);
+  indices.exportIdx(M);
+
+  std::random_device randomDevice;
+  std::mt19937 generator(randomDevice());
+  std::uniform_real_distribution<> distribution(0.1, 0.4);
+
+  for (auto it = M.begin(); it != M.end(); ++it) {
+    size_t const i = it.index();
+    for (auto cIt = it->begin(); cIt != it->end(); ++cIt) {
+      size_t const j = cIt.index();
+      *cIt = distribution(generator);
+      if (i == j)
+        *cIt += 0.6;
+    }
+  }
+
+  Dune::BlockVector<Dune::FieldVector<double, 1>> sol(n);
+  for (auto &x : sol)
+    x = distribution(generator);
+  Dune::BlockVector<Dune::FieldVector<double, 1>> b(n);
+  M.mv(sol, b);
+
+  Dune::BitSetVector<1> *ignore = nullptr;
+  {
+    auto x = lower ? Dune::MatrixVector::lowerTriangularSolve(M, b, ignore)
+                   : Dune::MatrixVector::upperTriangularSolve(M, b, ignore);
+    Dune::BlockVector<Dune::FieldVector<double, 1>> y(n);
+    M.mv(x, y);
+    auto diff = diffDune(b, y);
+    std::cout << "Difference: " << diff << std::endl;
+    passed &= diff < tol;
+  }
+  {
+    auto x = lower
+                 ? Dune::MatrixVector::upperTriangularSolve(M, b, ignore, true)
+                 : Dune::MatrixVector::lowerTriangularSolve(M, b, ignore, true);
+    Dune::BlockVector<Dune::FieldVector<double, 1>> y(n);
+    M.mtv(x, y);
+    auto diff = diffDune(b, y);
+    std::cout << "Difference: " << diff << std::endl;
+    passed &= diff < tol;
+  }
+  return passed;
+}
+
+int main() {
+  bool passed = true;
+  passed &= test<1000, false>();
+  passed &= test<1000, true>();
+  return passed ? 0 : 1;
+}