tests: Add tests for the python module

This doesn't touch everything as it's just based on the python3 module
tests, ported to the python module. It's still better than the one very
basic test in the unit test module.
pull/4616/head
Dylan Baker 6 years ago
parent f6405adc2d
commit 978e6fb88f
  1. 1
      run_project_tests.py
  2. 0
      test cases/python/1 basic/gluon/__init__.py
  3. 2
      test cases/python/1 basic/gluon/gluonator.py
  4. 26
      test cases/python/1 basic/meson.build
  5. 9
      test cases/python/1 basic/prog.py
  6. 4
      test cases/python/1 basic/subdir/meson.build
  7. 12
      test cases/python/1 basic/subdir/subprog.py
  8. 14
      test cases/python/2 extmodule/blaster.py
  9. 6
      test cases/python/2 extmodule/ext/meson.build
  10. 49
      test cases/python/2 extmodule/ext/tachyon_module.c
  11. 28
      test cases/python/2 extmodule/meson.build
  12. 23
      test cases/python/3 cython/cytest.py
  13. 9
      test cases/python/3 cython/libdir/cstorer.pxd
  14. 11
      test cases/python/3 cython/libdir/meson.build
  15. 24
      test cases/python/3 cython/libdir/storer.c
  16. 8
      test cases/python/3 cython/libdir/storer.h
  17. 16
      test cases/python/3 cython/libdir/storer.pyx
  18. 20
      test cases/python/3 cython/meson.build
  19. 32
      test cases/python/4 custom target depends extmodule/blaster.py
  20. 8
      test cases/python/4 custom target depends extmodule/ext/lib/meson-tachyonlib.c
  21. 6
      test cases/python/4 custom target depends extmodule/ext/lib/meson-tachyonlib.h
  22. 4
      test cases/python/4 custom target depends extmodule/ext/lib/meson.build
  23. 6
      test cases/python/4 custom target depends extmodule/ext/meson.build
  24. 51
      test cases/python/4 custom target depends extmodule/ext/tachyon_module.c
  25. 35
      test cases/python/4 custom target depends extmodule/meson.build

@ -543,6 +543,7 @@ def detect_tests_to_run():
('fortran', 'fortran', backend is not Backend.ninja or not shutil.which('gfortran')),
('swift', 'swift', backend not in (Backend.ninja, Backend.xcode) or not shutil.which('swiftc')),
('python3', 'python3', backend is not Backend.ninja),
('python', 'python', backend is not Backend.ninja),
('fpga', 'fpga', shutil.which('yosys') is None),
('frameworks', 'frameworks', False),
('nasm', 'nasm', False),

@ -0,0 +1,2 @@
def gluoninate():
return 42

@ -0,0 +1,26 @@
project('python sample', 'c')
py_mod = import('python')
py = py_mod.find_installation()
py_version = py.language_version()
if py_version.version_compare('< 3.2')
error('MESON_SKIP_TEST python 3 required for tests')
endif
py_purelib = py.get_path('purelib')
if not py_purelib.endswith('site-packages')
error('Python3 purelib path seems invalid? ' + py_purelib)
endif
# could be 'lib64' or 'Lib' on some systems
py_platlib = py.get_path('platlib')
if not py_platlib.endswith('site-packages')
error('Python3 platlib path seems invalid? ' + py_platlib)
endif
main = files('prog.py')
test('toplevel', py, args : main)
subdir('subdir')

@ -0,0 +1,9 @@
#!/usr/bin/env python3
from gluon import gluonator
import sys
print('Running mainprog from root dir.')
if gluonator.gluoninate() != 42:
sys.exit(1)

@ -0,0 +1,4 @@
test('subdir',
py,
args : files('subprog.py'),
env : 'PYTHONPATH=' + meson.source_root())

@ -0,0 +1,12 @@
#!/usr/bin/env python3
# In order to run this program, PYTHONPATH must be set to
# point to source root.
from gluon import gluonator
import sys
print('Running mainprog from subdir.')
if gluonator.gluoninate() != 42:
sys.exit(1)

@ -0,0 +1,14 @@
#!/usr/bin/env python3
import tachyon
import sys
result = tachyon.phaserize('shoot')
if not isinstance(result, int):
print('Returned result not an integer.')
sys.exit(1)
if result != 1:
print('Returned result {} is not 1.'.format(result))
sys.exit(1)

@ -0,0 +1,6 @@
pylib = py.extension_module('tachyon',
'tachyon_module.c',
dependencies : py_dep,
)
pypathdir = meson.current_build_dir()

@ -0,0 +1,49 @@
/*
Copyright 2016 The Meson development team
Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* A very simple Python extension module. */
#include <Python.h>
#include <string.h>
static PyObject* phaserize(PyObject *self, PyObject *args) {
const char *message;
int result;
if(!PyArg_ParseTuple(args, "s", &message))
return NULL;
result = strcmp(message, "shoot") ? 0 : 1;
return PyLong_FromLong(result);
}
static PyMethodDef TachyonMethods[] = {
{"phaserize", phaserize, METH_VARARGS,
"Shoot tachyon cannons."},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef tachyonmodule = {
PyModuleDef_HEAD_INIT,
"tachyon",
NULL,
-1,
TachyonMethods
};
PyMODINIT_FUNC PyInit_tachyon(void) {
return PyModule_Create(&tachyonmodule);
}

@ -0,0 +1,28 @@
project('Python extension module', 'c',
default_options : ['buildtype=release'])
# Because Windows Python ships only with optimized libs,
# we must build this project the same way.
py_mod = import('python')
py = py_mod.find_installation()
py_dep = py.dependency()
if py_dep.found()
subdir('ext')
test('extmod',
py,
args : files('blaster.py'),
env : ['PYTHONPATH=' + pypathdir])
# Check we can apply a version constraint
dependency('python3', version: '>=@0@'.format(py_dep.version()))
else
error('MESON_SKIP_TEST: Python3 libraries not found, skipping test.')
endif
py3_pkg_dep = dependency('python3', method: 'pkg-config', required : false)
if py3_pkg_dep.found()
python_lib_dir = py3_pkg_dep.get_pkgconfig_variable('libdir')
endif

@ -0,0 +1,23 @@
#!/usr/bin/env python3
from storer import Storer
import sys
s = Storer()
if s.get_value() != 0:
print('Initial value incorrect.')
sys.exit(1)
s.set_value(42)
if s.get_value() != 42:
print('Setting value failed.')
sys.exit(1)
try:
s.set_value('not a number')
print('Using wrong argument type did not fail.')
sys.exit(1)
except TypeError:
pass

@ -0,0 +1,9 @@
cdef extern from "storer.h":
ctypedef struct Storer:
pass
Storer* storer_new();
void storer_destroy(Storer *s);
int storer_get_value(Storer *s);
void storer_set_value(Storer *s, int v);

@ -0,0 +1,11 @@
pyx_c = custom_target('storer_pyx',
output : 'storer_pyx.c',
input : 'storer.pyx',
command : [cython, '@INPUT@', '-o', '@OUTPUT@'],
)
slib = py3.extension_module('storer',
'storer.c', pyx_c,
dependencies : py3_dep)
pydir = meson.current_build_dir()

@ -0,0 +1,24 @@
#include"storer.h"
#include<stdlib.h>
struct _Storer {
int value;
};
Storer* storer_new() {
Storer *s = malloc(sizeof(struct _Storer));
s->value = 0;
return s;
}
void storer_destroy(Storer *s) {
free(s);
}
int storer_get_value(Storer *s) {
return s->value;
}
void storer_set_value(Storer *s, int v) {
s->value = v;
}

@ -0,0 +1,8 @@
#pragma once
typedef struct _Storer Storer;
Storer* storer_new();
void storer_destroy(Storer *s);
int storer_get_value(Storer *s);
void storer_set_value(Storer *s, int v);

@ -0,0 +1,16 @@
cimport cstorer
cdef class Storer:
cdef cstorer.Storer* _c_storer
def __cinit__(self):
self._c_storer = cstorer.storer_new()
def __dealloc__(self):
cstorer.storer_destroy(self._c_storer)
cpdef int get_value(self):
return cstorer.storer_get_value(self._c_storer)
cpdef set_value(self, int value):
cstorer.storer_set_value(self._c_storer, value)

@ -0,0 +1,20 @@
project('cython', 'c',
default_options : ['warning_level=3'])
cython = find_program('cython3', required : false)
py3_dep = dependency('python3', required : false)
if cython.found() and py3_dep.found()
py_mod = import('python')
py3 = py_mod.find_installation()
py3_dep = py3.dependency()
subdir('libdir')
test('cython tester',
py3,
args : files('cytest.py'),
env : ['PYTHONPATH=' + pydir]
)
else
error('MESON_SKIP_TEST: Cython3 or Python3 libraries not found, skipping test.')
endif

@ -0,0 +1,32 @@
#!/usr/bin/env python3
import os
import sys
import argparse
from pathlib import Path
filedir = Path(os.path.dirname(__file__)).resolve()
if list(filedir.glob('ext/*tachyon*')):
sys.path.insert(0, (filedir / 'ext').as_posix())
import tachyon
parser = argparse.ArgumentParser()
parser.add_argument('-o', dest='output', default=None)
options = parser.parse_args(sys.argv[1:])
result = tachyon.phaserize('shoot')
if options.output:
with open(options.output, 'w') as f:
f.write('success')
if not isinstance(result, int):
print('Returned result not an integer.')
sys.exit(1)
if result != 1:
print('Returned result {} is not 1.'.format(result))
sys.exit(1)

@ -0,0 +1,8 @@
#ifdef _MSC_VER
__declspec(dllexport)
#endif
const char*
tachyon_phaser_command (void)
{
return "shoot";
}

@ -0,0 +1,6 @@
#pragma once
#ifdef _MSC_VER
__declspec(dllimport)
#endif
const char* tachyon_phaser_command (void);

@ -0,0 +1,4 @@
libtachyon = shared_library('tachyonlib', 'meson-tachyonlib.c')
libtachyon_dep = declare_dependency(link_with : libtachyon,
include_directories : include_directories('.'))

@ -0,0 +1,6 @@
subdir('lib')
pylib = py3.extension_module('tachyon',
'tachyon_module.c',
dependencies : [libtachyon_dep, py3_dep],
)

@ -0,0 +1,51 @@
/*
Copyright 2016 The Meson development team
Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/* A very simple Python extension module. */
#include <Python.h>
#include <string.h>
#include "meson-tachyonlib.h"
static PyObject* phaserize(PyObject *self, PyObject *args) {
const char *message;
int result;
if(!PyArg_ParseTuple(args, "s", &message))
return NULL;
result = strcmp(message, tachyon_phaser_command()) ? 0 : 1;
return PyLong_FromLong(result);
}
static PyMethodDef TachyonMethods[] = {
{"phaserize", phaserize, METH_VARARGS,
"Shoot tachyon cannons."},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef tachyonmodule = {
PyModuleDef_HEAD_INIT,
"tachyon",
NULL,
-1,
TachyonMethods
};
PyMODINIT_FUNC PyInit_tachyon(void) {
return PyModule_Create(&tachyonmodule);
}

@ -0,0 +1,35 @@
project('Python extension module', 'c',
default_options : ['buildtype=release'])
# Because Windows Python ships only with optimized libs,
# we must build this project the same way.
py_mod = import('python')
py3 = py_mod.find_installation()
py3_dep = py3.dependency(required : false)
# Copy to the builddir so that blaster.py can find the built tachyon module
# FIXME: We should automatically detect this case and append the correct paths
# to PYTHONLIBDIR
blaster_py = configure_file(input : 'blaster.py',
output : 'blaster.py',
copy : true)
check_exists = '''
import os, sys
with open(sys.argv[1], 'rb') as f:
assert(f.read() == b'success')
'''
if py3_dep.found()
subdir('ext')
out_txt = custom_target('tachyon flux',
input : blaster_py,
output : 'out.txt',
command : [py3, '@INPUT@', '-o', '@OUTPUT@'],
depends : pylib,
build_by_default: true)
test('flux', py3, args : ['-c', check_exists, out_txt])
else
error('MESON_SKIP_TEST: Python3 libraries not found, skipping test.')
endif
Loading…
Cancel
Save