File: conftest.py

package info (click to toggle)
dijitso 2018.1.1~git1-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 420 kB
  • sloc: python: 1,672; makefile: 194; sh: 53; ansic: 1
file content (184 lines) | stat: -rw-r--r-- 4,871 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/env py.test
# -*- coding: utf-8 -*-

import pytest
import os
import dijitso
import ctypes


@pytest.fixture()
def comm():
    try:
        from mpi4py import MPI
        c = MPI.COMM_WORLD
    except ImportError:
        pytest.skip("Need mpi4py to test with comms.")
        c = None
    return c


_code_template_params = """\
/**
Arguments used to generate this code:
%(generator_params)s
*/
"""

_code_template_defines = """\
// Based on https://gcc.gnu.org/wiki/Visibility
#if defined _WIN32 || defined __CYGWIN__
    #ifdef __GNUC__
        #define DLL_EXPORT extern "C" __attribute__ ((dllexport))
    #else
        #define DLL_EXPORT extern "C" __declspec(dllexport)
    #endif
#else
    #define DLL_EXPORT extern "C" __attribute__ ((visibility ("default")))
#endif
"""

_code_template_interface = """\
// This would be '#include <ufc.h>'
class %(interfacename)s
{
public:
    virtual ~%(interfacename)s() {}

    virtual int get_test_value() const = 0;
};
"""

_code_template_class = """\
/// This would be the generated ufc::form code
class %(classname)s: public %(interfacename)s
{
public:
    int get_test_value() const
    { return %(testvalue)s; }
};
"""

_code_template_factory = """\
/// Construct an object of class %(classname)s without any class interface wrapping
DLL_EXPORT void * create_%(signature)s()
{
    return new %(classname)s();
}
"""

_code_template_testhook = """\
#include "testinclude.h"
DLL_EXPORT int get_test_value_%(testvalue)d(void * p)
{
    %(interfacename)s * pp = static_cast<%(interfacename)s *>(p);
    int v = pp->get_test_value();
    return v + TESTINCLUDE_MAGIC_VALUE;
}
"""


def mygenerate(jitable, name, signature, generator_params):
    """."""
    code_parts = dict(
        generator_params=str(generator_params),
        signature=signature,
        classname="class_%s" % (jitable,),
        interfacename="external_interface",
        testvalue=jitable,
    )
    parts = [
        _code_template_params % code_parts,
        _code_template_defines % code_parts,
        _code_template_interface % code_parts,
        _code_template_class % code_parts,
        _code_template_factory % code_parts,
        _code_template_testhook % code_parts,
    ]
    header = "// Dummy header"
    source = '\n'.join(parts)
    dependencies = ()
    return header, source, dependencies


_default_dijitso_cache_dir = os.path.join(os.path.dirname(__file__), ".dijitso")
_testincludes = os.path.join(os.path.dirname(__file__), "testincludes")


def _jit_integer(jitable, comm=None, buildon="node",
                 dijitso_cache_dir=_default_dijitso_cache_dir):
    "A mock jit routine setup to exercise much of the library."

    # Setup params
    cache_params = dict(
        cache_dir=dijitso_cache_dir,
        src_storage="compress",
    )
    build_params = dict(
        debug=True,
        include_dirs=(_testincludes,),
    )
    generator_params = None
    params = dict(
        cache=cache_params,
        build=build_params,
        generator=generator_params,
    )
    params = dijitso.validate_params(params)

    # Compute a name
    from dijitso.signatures import hashit
    name = "jit_integer_" + hashit(jitable)

    # Autodetect subcomms and role based on buildin option and
    # physical disk access of processes
    from dijitso.mpi import create_comms_and_role, send_binary, receive_binary
    from dijitso.system import make_dirs
    sync_dir = os.path.join(cache_params["cache_dir"], "sync")
    make_dirs(sync_dir)
    copy_comm, wait_comm, role = create_comms_and_role(comm, sync_dir, buildon)

    # Somewhat messy definitions of send/receive/wait...
    send = None
    receive = None
    wait = None
    if role == "builder":
        generate = mygenerate
        if copy_comm is not None:
            def send(lib_data):
                assert role == "builder"
                send_binary(copy_comm, lib_data)
    elif role == "receiver":
        generate = None
        assert copy_comm is not None

        def receive():
            return receive_binary(copy_comm)
    elif role == "waiter":
        generate = None

    if wait_comm is not None:
        def wait():
            wait_comm.barrier()

    # Jit it!
    lib, signature = dijitso.jit(jitable, name, params,
                                 generate, send, receive, wait)

    assert lib is not None
    assert isinstance(signature, str)

    # Extract the factory function we want from library
    factory = dijitso.extract_factory_function(lib, "create_" + signature)
    # ... and the test specific getter function
    get_test_value = getattr(lib, "get_test_value_%d" % jitable)
    get_test_value.argtypes = [ctypes.c_void_p]
    get_test_value.restype = ctypes.c_int

    # Return both library and factory
    return lib, factory, get_test_value


@pytest.fixture()
def jit_integer():
    return _jit_integer