From 3e9f1e00feff62670888a307562092cb6b015099 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20He=C3=9F?= <rene@debian>
Date: Fri, 30 Sep 2016 15:47:07 +0200
Subject: [PATCH] Test cache behaviour

---
 python/CMakeLists.txt                         |   2 +
 python/dune/perftool/pdelab/localoperator.py  |   4 +-
 python/test/CMakeLists.txt                    |   1 +
 python/test/dune/CMakeLists.txt               |   1 +
 python/test/dune/perftool/CMakeLists.txt      |   1 +
 .../dune/perftool/generation/CMakeLists.txt   |   3 +
 .../dune/perftool/generation/test_cache.py    | 233 ++++++++++++++++++
 7 files changed, 243 insertions(+), 2 deletions(-)
 create mode 100644 python/test/CMakeLists.txt
 create mode 100644 python/test/dune/CMakeLists.txt
 create mode 100644 python/test/dune/perftool/CMakeLists.txt
 create mode 100644 python/test/dune/perftool/generation/CMakeLists.txt
 create mode 100644 python/test/dune/perftool/generation/test_cache.py

diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 3e72e618..b04dea7b 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -20,3 +20,5 @@ dune_install_python_package(PATH .)
 add_python_test_command(COMMAND python -m pytest --pep8
                         WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python/dune/perftool
                         REQUIRED_PACKAGES pytest pytest-pep8)
+
+add_subdirectory(test)
diff --git a/python/dune/perftool/pdelab/localoperator.py b/python/dune/perftool/pdelab/localoperator.py
index 7936437e..475c052d 100644
--- a/python/dune/perftool/pdelab/localoperator.py
+++ b/python/dune/perftool/pdelab/localoperator.py
@@ -471,7 +471,7 @@ def generate_localoperator_kernels(formdata, data):
                             # Numerical jacobian apply initializer list
                             initializer_list("Dune::PDELab::NumericalJacobianApply{}<{}>".format(which, loptype),
                                              ["{}.get<double>(\"numerical_epsilon.{}\", 1e-9)".format(ini_constructor, ini, which.lower())],
-                                              classtag="operator",
+                                             classtag="operator",
                                              )
                         else:
                             # Numerical nonlinear jacobian apply base class
@@ -480,7 +480,7 @@ def generate_localoperator_kernels(formdata, data):
                             # Numerical nonlinear jacobian apply initializer list
                             initializer_list("Dune::PDELab::NumericalNonlinearJacobianApply{}<{}>".format(which, loptype),
                                              ["{}.get<double>(\"numerical_epsilon.{}\", 1e-9)".format(ini_constructor, ini, which.lower())],
-                                              classtag="operator",
+                                             classtag="operator",
                                              )
 
                 operator_kernels[(measure, 'residual')] = kernel
diff --git a/python/test/CMakeLists.txt b/python/test/CMakeLists.txt
new file mode 100644
index 00000000..22fc2134
--- /dev/null
+++ b/python/test/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(dune)
diff --git a/python/test/dune/CMakeLists.txt b/python/test/dune/CMakeLists.txt
new file mode 100644
index 00000000..aa7576d1
--- /dev/null
+++ b/python/test/dune/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(perftool)
diff --git a/python/test/dune/perftool/CMakeLists.txt b/python/test/dune/perftool/CMakeLists.txt
new file mode 100644
index 00000000..f7023229
--- /dev/null
+++ b/python/test/dune/perftool/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(generation)
diff --git a/python/test/dune/perftool/generation/CMakeLists.txt b/python/test/dune/perftool/generation/CMakeLists.txt
new file mode 100644
index 00000000..47b168ae
--- /dev/null
+++ b/python/test/dune/perftool/generation/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_python_test_command(COMMAND python -m pytest --pep8
+                        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python/test/dune/perftool/generation
+                        REQUIRED_PACKAGES pytest pytest-pep8)
diff --git a/python/test/dune/perftool/generation/test_cache.py b/python/test/dune/perftool/generation/test_cache.py
new file mode 100644
index 00000000..4bdc47ae
--- /dev/null
+++ b/python/test/dune/perftool/generation/test_cache.py
@@ -0,0 +1,233 @@
+from collections import Counter
+
+from dune.perftool.generation.cache import(delete_cache_items,
+                                           generator_factory,
+                                           no_caching,
+                                           retrieve_cache_functions,
+                                           retrieve_cache_items,
+                                           )
+
+
+def print_cache():
+    """Print all cache items"""
+    for i in retrieve_cache_items("True"):
+        print i
+
+
+# ================================================
+# Test retrieve_cache_items and delete_cache_items
+# ================================================
+
+
+# Some generators
+gen_foo = generator_factory(item_tags=("foo",))
+gen_bar = generator_factory(item_tags=("bar",))
+gen_foobar = generator_factory(item_tags=("foo", "bar"))
+
+
+# Some decorated functions
+@gen_foo
+def foo(name):
+    return "foo {}".format(name)
+
+
+@gen_bar
+def bar(name):
+    return "bar {}".format(name)
+
+
+@gen_foobar
+def foobar(name):
+    return "foobar {}".format(name)
+
+
+# Will add two cache entries one with tag foo and one with tag bar
+@gen_foo
+@gen_bar
+def foobar_two(name):
+    return "foobar_two {}".format(name)
+
+
+def setup_cache():
+    """Empty cache and fill it in a specific way
+
+    After calling this function the cache will be filled with the
+    following entries:
+
+    foo foo (tag foo)
+    foobar_two foobar_two_1 (tag foo)
+    bar bar_1 (tag bar)
+    bar bar_2 (tag bar)
+    foobar_two foobar_two_1 (tag bar)
+    foobar foobar (tag foo and bar)
+
+    """
+    delete_cache_items()
+    assert not list(retrieve_cache_items("True"))
+
+    foo("foo")
+    bar("bar_1")
+    bar("bar_2")
+    foobar("foobar")
+    foobar_two("foobar_two")
+
+    # This call shouldn't change anything
+    foo("foo")
+
+    # print_cache()
+
+
+# Some lists for comparison
+# Empty
+list_empty = []
+list_not_foo_not_bar = []
+
+
+# One field
+list_foo_not_bar = ["foo foo", "foobar_two foobar_two"]
+list_not_foo_and_bar = ["bar bar_1", "bar bar_2", "foobar_two foobar_two"]
+list_foo_and_bar = ["foobar foobar"]
+
+
+# Two fields
+list_foo = list_foo_not_bar + list_foo_and_bar
+list_bar = list_not_foo_and_bar + list_foo_and_bar
+list_not_foobar = list_foo_not_bar + list_not_foo_and_bar
+
+
+# All three fields
+list_foo_or_bar = list_foo_not_bar + list_not_foo_and_bar + list_foo_and_bar
+list_full = list_foo_or_bar
+
+
+def compare(x, y):
+    """Compare if lists x and y have the same entries
+
+    Having the same entries means:
+
+    - If item a can be found k times in x it must also be k times in y
+    - Vice versa.
+    - Ordering of items doesn't matter.
+    """
+    return Counter(x) == Counter(y)
+
+
+def test_retrieve_cache():
+    """Test all combinations of retrieve_cache for our test setup"""
+    # Setup cache in the way descibed above
+    setup_cache()
+
+    # Load global lists for comparison
+    global list_empty
+    global list_not_foo_not_bar
+
+    global list_foo_not_bar
+    global list_not_foo_and_bar
+    global list_foo_and_bar
+
+    global list_foo
+    global list_bar
+    global list_not_foobar
+
+    global list_foo_or_bar
+    global list_full
+
+    # Empty
+    assert compare(list_empty, list(retrieve_cache_items("False")))
+    assert compare(list_not_foo_not_bar, list(retrieve_cache_items("not foo and not bar")))
+
+    # One field
+    assert compare(list_foo_not_bar, list(retrieve_cache_items("foo and not bar")))
+    assert compare(list_not_foo_and_bar, list(retrieve_cache_items("not foo and bar")))
+    assert compare(list_foo_and_bar, list(retrieve_cache_items("foo and bar")))
+
+    # Two fields
+    assert compare(list_foo, list(retrieve_cache_items("foo")))
+    assert compare(list_bar, list(retrieve_cache_items("bar")))
+    assert compare(list_not_foobar, list(retrieve_cache_items("not (foo and bar)")))
+
+    # All three fields
+    assert compare(list_foo_or_bar, list(retrieve_cache_items("foo or bar")))
+    assert compare(list_full, list(retrieve_cache_items("True")))
+
+
+def test_delete_cache_items():
+    """Test all combinations of delete_cache_items for our test setup"""
+    # Load global list used for comparison
+    global list_empty
+    global list_not_foo_not_bar
+
+    global list_foo_not_bar
+    global list_not_foo_and_bar
+    global list_foo_and_bar
+
+    global list_foo
+    global list_bar
+    global list_not_foobar
+
+    global list_foo_or_bar
+    global list_full
+
+    # Tests deleting "all three fields"
+    setup_cache()
+    delete_cache_items("True")
+    assert compare(list_empty, list(retrieve_cache_items("True")))
+
+    setup_cache()
+    delete_cache_items("foo or bar")
+    assert compare(list_not_foo_not_bar, list(retrieve_cache_items("True")))
+
+    # Tests deleting "two fields"
+    setup_cache()
+    delete_cache_items("bar")
+    assert compare(list_foo_not_bar, list(retrieve_cache_items("True")))
+
+    setup_cache()
+    delete_cache_items("foo")
+    assert compare(list_not_foo_and_bar, list(retrieve_cache_items("True")))
+
+    setup_cache()
+    delete_cache_items("(foo and not bar) or (not foo and bar)")
+    assert compare(list_foo_and_bar, list(retrieve_cache_items("True")))
+
+    # Tests deleting "one field"
+    setup_cache()
+    delete_cache_items("not foo and bar")
+    assert compare(list_foo, list(retrieve_cache_items("True")))
+
+    setup_cache()
+    delete_cache_items("foo and not bar")
+    assert compare(list_bar, list(retrieve_cache_items("True")))
+
+    setup_cache()
+    delete_cache_items("foo and bar")
+    assert compare(list_not_foobar, list(retrieve_cache_items("True")))
+
+    # Tests deleting nothing
+    setup_cache()
+    delete_cache_items("not foo and not bar")
+    assert compare(list_foo_or_bar, list(retrieve_cache_items("True")))
+
+    setup_cache()
+    delete_cache_items("False")
+    assert compare(list_full, list(retrieve_cache_items("True")))
+
+
+# ===============
+# Test no caching
+# ===============
+
+
+@generator_factory(item_tags=("no_caching",), cache_key_generator=no_caching)
+def no_caching_function(name):
+    return "{}".format(name)
+
+
+def test_no_caching_function():
+    delete_cache_items()
+    no_caching_function("one")
+    assert compare(["one"], list(retrieve_cache_items("no_caching")))
+    no_caching_function("one")
+    assert compare(["one", "one"], list(retrieve_cache_items("no_caching")))
+    no_caching_function("two")
+    assert compare(["one", "one", "two"], list(retrieve_cache_items("no_caching")))
-- 
GitLab