diff --git a/CMakeLists.txt b/CMakeLists.txt index e4d40b9..5312617 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,9 +78,10 @@ option (RPM "Generate RPM using CPack" OFF) option (ENABLEEXAMPLES "Disable building of examples" ON) option (INSTALLGPIOTOOL "Install gpio tool" OFF) option (INSTALLTOOLS "Install all tools" OFF) -option (BUILDARCH "Override architecture to build for - override" OFF) option (BUILDTESTS "Override the addition of tests" ON) +set (BUILDARCH "" CACHE STRING "Override architecture to build for") + set (MRAAPLATFORMFORCE "ALL" CACHE STRING "Override platform to build for") if (NOT BUILDSWIG) @@ -103,8 +104,10 @@ if (DETECTED_ARCH STREQUAL "i586" OR DETECTED_ARCH STREQUAL "x86_64" set (X86PLAT ON) elseif (DETECTED_ARCH MATCHES "arm.*") set (ARMPLAT ON) +elseif (DETECTED_ARCH STREQUAL "MOCK") + set (MOCKPLAT ON) else () - message (FATAL_ERROR "Only x86 and arm platforms currently supported") + message (FATAL_ERROR "Only x86, arm and mock platforms currently supported") endif() if (BUILDSWIGPYTHON OR BUILDTESTS) diff --git a/README.md b/README.md index 4a2a182..e9fdab5 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,10 @@ USB --- * [FT4222](../master/docs/ftdi_ft4222.md) +Mock +---- +* [Generic simulated board](../master/docs/mock.md) + Installing on your board ======== diff --git a/api/mraa/types.h b/api/mraa/types.h index 5c43dd4..da479b9 100644 --- a/api/mraa/types.h +++ b/api/mraa/types.h @@ -58,6 +58,7 @@ typedef enum { // contains bit 9 so is subplatform MRAA_GENERIC_FIRMATA = 1280, /**< Firmata uart platform/bridge */ + MRAA_MOCK_PLATFORM = 96, /**< Mock platform, which requires no real hardware */ MRAA_NULL_PLATFORM = 98, /**< Platform with no capabilities that hosts a sub platform */ MRAA_UNKNOWN_PLATFORM = 99 /**< An unknown platform type, typically will load INTEL_GALILEO_GEN1 */ diff --git a/docs/mock.md b/docs/mock.md new file mode 100644 index 0000000..f2346d8 --- /dev/null +++ b/docs/mock.md @@ -0,0 +1,37 @@ +Mock platform {#mock} +============= + +Mocking capability allows libmraa user to work with the library without any real +hardware available. Enabling this requires library recompilation with architecture +override (see Building section below). When mock is enabled, library simulates +actual HW operations at the backend so that for the application it looks +like a usual board. Being implemented at the backend, the functionality is available +in all language bindings libmraa supports. + +Board configuration +------------------- + +This feature is yet in the experimental mode and not all functionality is available. +Right now we simulate a single generic board with only GPIO (without ISR) working. +It also reports having an ADC with 10 (std)/12 (max) bit resolution, but the ADC +functionality itself is not yet implemented. + +We plan to develop it further and all [contributions](../CONTRIBUTING.md) are more than welcome. + +See the table below for pin layout and features + +| MRAA Number | Pin Name | Notes | +|-------------|----------|-----------------------------| +| 0 | GPIO0 | GPIO pin, no muxing, no ISR | + +Building +-------- + +Generally all the building steps are the same as listed +in the [main building guide](./building.md), you just need to set some specific +CMake options. + +### Linux + +To build under Linux, follow standard instructions, just make sure to set +the `-DBUILDARCH="MOCK"` CMake option. diff --git a/include/mock/mock_board.h b/include/mock/mock_board.h new file mode 100644 index 0000000..922dbf9 --- /dev/null +++ b/include/mock/mock_board.h @@ -0,0 +1,40 @@ +/* + * Author: Alex Tereschenko + * Copyright (c) 2016 Alex Tereschenko. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mraa_internal.h" + +#define MRAA_MOCK_PINCOUNT 1 + +mraa_board_t* +mraa_mock_board(); + +#ifdef __cplusplus +} +#endif diff --git a/include/mraa_adv_func.h b/include/mraa_adv_func.h index ea7fe98..40cae5d 100644 --- a/include/mraa_adv_func.h +++ b/include/mraa_adv_func.h @@ -48,6 +48,7 @@ typedef struct { mraa_result_t (*gpio_dir_replace) (mraa_gpio_context dev, mraa_gpio_dir_t dir); mraa_result_t (*gpio_dir_pre) (mraa_gpio_context dev, mraa_gpio_dir_t dir); mraa_result_t (*gpio_dir_post) (mraa_gpio_context dev, mraa_gpio_dir_t dir); + mraa_result_t (*gpio_read_dir_replace) (mraa_gpio_context dev, mraa_gpio_dir_t *dir); int (*gpio_read_replace) (mraa_gpio_context dev); mraa_result_t (*gpio_write_replace) (mraa_gpio_context dev, int value); @@ -56,6 +57,8 @@ typedef struct { mraa_result_t (*gpio_mmap_setup) (mraa_gpio_context dev, mraa_boolean_t en); mraa_result_t (*gpio_interrupt_handler_init_replace) (mraa_gpio_context dev); mraa_result_t (*gpio_wait_interrupt_replace) (mraa_gpio_context dev); + mraa_result_t (*gpio_isr_replace) (mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), void* args); + mraa_result_t (*gpio_isr_exit_replace) (mraa_gpio_context dev); mraa_result_t (*i2c_init_pre) (unsigned int bus); mraa_result_t (*i2c_init_bus_replace) (mraa_i2c_context dev); diff --git a/include/mraa_internal.h b/include/mraa_internal.h index edd65d8..05e42dc 100644 --- a/include/mraa_internal.h +++ b/include/mraa_internal.h @@ -62,6 +62,13 @@ mraa_platform_t mraa_x86_platform(); */ mraa_platform_t mraa_arm_platform(); +/** + * setup a mock platform + * + * @return mraa_platform_t of the init'ed platform + */ +mraa_platform_t mraa_mock_platform(); + /** * runtime detect running usb platform extender * diff --git a/include/mraa_internal_types.h b/include/mraa_internal_types.h index 2873d4a..8220746 100644 --- a/include/mraa_internal_types.h +++ b/include/mraa_internal_types.h @@ -71,6 +71,10 @@ struct _gpio { mraa_result_t (*mmap_write) (mraa_gpio_context dev, int value); int (*mmap_read) (mraa_gpio_context dev); mraa_adv_func_t* advance_func; /**< override function table */ +#if defined(MOCKPLAT) + mraa_gpio_dir_t mock_dir; /**< mock direction of the pin */ + int mock_state; /**< mock state of the pin */ +#endif /*@}*/ }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f5adb2..c498233 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -84,6 +84,11 @@ set (mraa_LIB_ARM_SRCS_NOAUTO ${PROJECT_SOURCE_DIR}/src/arm/banana.c ) +set (mraa_LIB_MOCK_SRCS_NOAUTO + ${PROJECT_SOURCE_DIR}/src/mock/mock.c + ${PROJECT_SOURCE_DIR}/src/mock/mock_board.c +) + set (mraa_LIBS ${CMAKE_THREAD_LIBS_INIT}) if (X86PLAT) @@ -96,6 +101,11 @@ if (ARMPLAT) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DARMPLAT=1") endif() +if (MOCKPLAT) + add_subdirectory(mock) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMOCKPLAT=1") +endif() + if (USBPLAT) message (STATUS "INFO - Adding USB platforms") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSBPLAT=1") diff --git a/src/gpio/gpio.c b/src/gpio/gpio.c index 6488fd5..1bab352 100644 --- a/src/gpio/gpio.c +++ b/src/gpio/gpio.c @@ -382,6 +382,10 @@ mraa_gpio_isr(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), return MRAA_ERROR_INVALID_HANDLE; } + if (IS_FUNC_DEFINED(dev, gpio_isr_replace)) { + return dev->advance_func->gpio_isr_replace(dev, mode, fptr, args); + } + // we only allow one isr per mraa_gpio_context if (dev->thread_id != 0) { return MRAA_ERROR_NO_RESOURCES; @@ -417,6 +421,10 @@ mraa_gpio_isr_exit(mraa_gpio_context dev) return MRAA_ERROR_INVALID_HANDLE; } + if (IS_FUNC_DEFINED(dev, gpio_isr_exit_replace)) { + return dev->advance_func->gpio_isr_exit_replace(dev); + } + // wasting our time, there is no isr to exit from if (dev->thread_id == 0 && dev->isr_value_fp == -1) { return ret; @@ -610,6 +618,10 @@ mraa_gpio_read_dir(mraa_gpio_context dev, mraa_gpio_dir_t *dir) return MRAA_ERROR_INVALID_HANDLE; } + if (IS_FUNC_DEFINED(dev, gpio_read_dir_replace)) { + return dev->advance_func->gpio_read_dir_replace(dev, dir); + } + snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/direction", dev->pin); fd = open(filepath, O_RDONLY); if (fd == -1) { diff --git a/src/mock/CMakeLists.txt b/src/mock/CMakeLists.txt new file mode 100644 index 0000000..eac1b59 --- /dev/null +++ b/src/mock/CMakeLists.txt @@ -0,0 +1,3 @@ +message (INFO " - Adding mock platform") +set (mraa_LIB_PLAT_SRCS_NOAUTO ${mraa_LIB_SRCS_NOAUTO} + ${mraa_LIB_MOCK_SRCS_NOAUTO} PARENT_SCOPE) diff --git a/src/mock/mock.c b/src/mock/mock.c new file mode 100644 index 0000000..e4fa220 --- /dev/null +++ b/src/mock/mock.c @@ -0,0 +1,43 @@ +/* + * Author: Alex Tereschenko + * Copyright (c) 2016 Alex Tereschenko. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include "mraa_internal.h" + +#include "mock/mock_board.h" + +mraa_platform_t +mraa_mock_platform() +{ + mraa_platform_t platform_type = MRAA_MOCK_PLATFORM; + plat = mraa_mock_board(); + + if (plat == NULL) { + syslog(LOG_ERR, "Was not able to initialize mock platform"); + return MRAA_ERROR_PLATFORM_NOT_INITIALISED; + } + + return platform_type; +} diff --git a/src/mock/mock_board.c b/src/mock/mock_board.c new file mode 100644 index 0000000..9fccf42 --- /dev/null +++ b/src/mock/mock_board.c @@ -0,0 +1,193 @@ +/* + * Author: Alex Tereschenko + * Copyright (c) 2016 Alex Tereschenko. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "common.h" +#include "mock/mock_board.h" + +#define PLATFORM_NAME "MRAA mock platform" + +mraa_result_t +mraa_mock_gpio_init_internal_replace(mraa_gpio_context dev, int pin) +{ + dev->value_fp = -1; + dev->isr_value_fp = -1; + dev->isr_thread_terminating = 0; + dev->phy_pin = pin; + // We are always the owner + dev->owner = 1; +#ifndef HAVE_PTHREAD_CANCEL + dev->isr_control_pipe[0] = dev->isr_control_pipe[1] = -1; +#endif + + // We start as INPUT and LOW + dev->mock_dir = MRAA_GPIO_IN; + dev->mock_state = 0; + + return MRAA_SUCCESS; +} + +mraa_result_t +mraa_mock_gpio_close_replace(mraa_gpio_context dev) +{ + free(dev); + return MRAA_SUCCESS; +} + +mraa_result_t +mraa_mock_gpio_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t dir) +{ + switch (dir) { + case MRAA_GPIO_OUT_HIGH: + dev->mock_dir = MRAA_GPIO_OUT; + return mraa_gpio_write(dev, 1); + case MRAA_GPIO_OUT_LOW: + dev->mock_dir = MRAA_GPIO_OUT; + return mraa_gpio_write(dev, 0); + case MRAA_GPIO_IN: + case MRAA_GPIO_OUT: + dev->mock_dir = dir; + return MRAA_SUCCESS; + default: + syslog(LOG_ERR, "gpio: dir: invalid direction '%d' to set", (int) dir); + return MRAA_ERROR_INVALID_PARAMETER; + } +} + +mraa_result_t +mraa_mock_gpio_read_dir_replace(mraa_gpio_context dev, mraa_gpio_dir_t* dir) +{ + *dir = dev->mock_dir; + return MRAA_SUCCESS; +} + +int +mraa_mock_gpio_read_replace(mraa_gpio_context dev) +{ + return dev->mock_state; +} + +mraa_result_t +mraa_mock_gpio_write_replace(mraa_gpio_context dev, int value) +{ + if ((value < 0) || (value > 1)) { + syslog(LOG_ERR, "gpio: write: incorrect value '%d' passed to write(), must be 0 or 1", value); + return MRAA_ERROR_INVALID_PARAMETER; + } + + if (dev->mock_dir == MRAA_GPIO_IN) { + syslog(LOG_ERR, "gpio: write: cannot write to pin set to INPUT"); + return MRAA_ERROR_INVALID_RESOURCE; + } + + dev->mock_state = value; + return MRAA_SUCCESS; +} + +mraa_result_t +mraa_mock_gpio_edge_mode_replace(mraa_gpio_context dev, mraa_gpio_edge_t mode) +{ + return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +mraa_result_t +mraa_mock_gpio_isr_replace(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), void* args) +{ + return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +mraa_result_t +mraa_mock_gpio_isr_exit_replace(mraa_gpio_context dev) +{ + return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +mraa_result_t +mraa_mock_gpio_mode_replace(mraa_gpio_context dev, mraa_gpio_mode_t mode) +{ + return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +mraa_board_t* +mraa_mock_board() +{ + mraa_board_t* b = (mraa_board_t*) calloc(1, sizeof(mraa_board_t)); + if (b == NULL) { + return NULL; + } + + // General board definitions + b->platform_name = PLATFORM_NAME; + b->phy_pin_count = MRAA_MOCK_PINCOUNT; + b->aio_count = 1; + b->adc_raw = 12; + b->adc_supported = 10; + b->i2c_bus_count = 0; + b->spi_bus_count = 0; + + b->pwm_default_period = 0; + b->pwm_max_period = 0; + b->pwm_min_period = 0; + + b->pins = (mraa_pininfo_t*) malloc(sizeof(mraa_pininfo_t) * MRAA_MOCK_PINCOUNT); + if (b->pins == NULL) { + goto error; + } + + b->adv_func = (mraa_adv_func_t*) calloc(1, sizeof(mraa_adv_func_t)); + if (b->adv_func == NULL) { + free(b->pins); + goto error; + } + + // Replace functions + b->adv_func->gpio_init_internal_replace = &mraa_mock_gpio_init_internal_replace; + b->adv_func->gpio_close_replace = &mraa_mock_gpio_close_replace; + b->adv_func->gpio_dir_replace = &mraa_mock_gpio_dir_replace; + b->adv_func->gpio_read_dir_replace = &mraa_mock_gpio_read_dir_replace; + b->adv_func->gpio_read_replace = &mraa_mock_gpio_read_replace; + b->adv_func->gpio_write_replace = &mraa_mock_gpio_write_replace; + b->adv_func->gpio_edge_mode_replace = &mraa_mock_gpio_edge_mode_replace; + b->adv_func->gpio_isr_replace = &mraa_mock_gpio_isr_replace; + b->adv_func->gpio_isr_exit_replace = &mraa_mock_gpio_isr_exit_replace; + b->adv_func->gpio_mode_replace = &mraa_mock_gpio_mode_replace; + + // Pin definitions + int pos = 0; + + strncpy(b->pins[pos].name, "GPIO0", 8); + b->pins[pos].capabilites = (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }; + b->pins[pos].gpio.pinmap = 0; + b->pins[pos].gpio.mux_total = 0; + pos++; + + return b; + +error: + syslog(LOG_CRIT, "MRAA mock: Platform failed to initialise"); + free(b); + return NULL; +} diff --git a/src/mraa.c b/src/mraa.c index 277b5d1..e42b734 100644 --- a/src/mraa.c +++ b/src/mraa.c @@ -120,6 +120,9 @@ imraa_init() #elif defined(ARMPLAT) // Use runtime ARM platform detection platform_type = mraa_arm_platform(); +#elif defined(MOCKPLAT) + // Use mock platform + platform_type = mraa_mock_platform(); #else #error mraa_ARCH NOTHING #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index df3baf8..2ea91ad 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,12 +14,16 @@ if (BUILDSWIGPYTHON) elseif (PYTHON3INTERP_FOUND) set (PYTHON_DEFAULT_PYTHONPATH "${CMAKE_BINARY_DIR}/src/python/python3") endif () - add_test (NAME py_general COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/general_checks.py) - set_tests_properties(py_general PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") + if (MOCKPLAT) + add_subdirectory (mock) + else() + add_test (NAME py_general COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/general_checks.py) + set_tests_properties(py_general PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") - add_test (NAME py_platform COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/platform_checks.py) - set_tests_properties(py_platform PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") + add_test (NAME py_platform COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/platform_checks.py) + set_tests_properties(py_platform PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") - add_test (NAME py_gpio COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks.py) - set_tests_properties(py_gpio PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") + add_test (NAME py_gpio COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks.py) + set_tests_properties(py_gpio PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") + endif() endif() diff --git a/tests/mock/CMakeLists.txt b/tests/mock/CMakeLists.txt new file mode 100644 index 0000000..be2cef5 --- /dev/null +++ b/tests/mock/CMakeLists.txt @@ -0,0 +1,19 @@ +# Mock platform tests +add_test (NAME py_general COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/general_checks.py) +add_test (NAME py_platform COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/platform_checks.py) +add_test (NAME py_gpio_basic COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks_basic.py) +add_test (NAME py_gpio_dir COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks_dir.py) +add_test (NAME py_gpio_write_read COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks_write_read.py) +add_test (NAME py_gpio_edge COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks_edge.py) +add_test (NAME py_gpio_isr COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks_isr.py) +add_test (NAME py_gpio_mode COMMAND ${PYTHON_DEFAULT_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gpio_checks_mode.py) + +set_tests_properties(py_general + py_platform + py_gpio_basic + py_gpio_dir + py_gpio_write_read + py_gpio_edge + py_gpio_isr + py_gpio_mode + PROPERTIES ENVIRONMENT "PYTHONPATH=${PYTHON_DEFAULT_PYTHONPATH}") diff --git a/tests/mock/general_checks.py b/tests/mock/general_checks.py new file mode 100755 index 0000000..5d7195b --- /dev/null +++ b/tests/mock/general_checks.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +# Author: Costin Constantin +# Copyright (c) 2015 Intel Corporation. +# +# Contributors: Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +class GeneralChecks(u.TestCase): + def test_mraa_version(self): + version = m.getVersion() + print("Version is: " + version) + self.assertIsNotNone(version) + self.assertNotEqual(version, "", "MRAA version is an empty string") + +if __name__ == "__main__": + u.main() diff --git a/tests/mock/gpio_checks_basic.py b/tests/mock/gpio_checks_basic.py new file mode 100755 index 0000000..48a86aa --- /dev/null +++ b/tests/mock/gpio_checks_basic.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# Author: Alex Tereschenko +# Copyright (c) 2016 Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +MRAA_TEST_PIN = 0 + +class GpioChecksBasic(u.TestCase): + def setUp(self): + self.pin = m.Gpio(MRAA_TEST_PIN) + + def tearDown(self): + del self.pin + + def test_gpio_state_after_init(self): + # After GPIO init it should be in INPUT and LOW state + self.assertEqual(self.pin.read(), 0, "GPIO is in a wrong state after init") + + def test_gpio_dir_after_init(self): + # After GPIO init it should be in INPUT and LOW state + self.assertEqual(self.pin.readDir(), m.DIR_IN, "GPIO has wrong direction after init") + + def test_get_pin_num(self): + self.assertEqual(self.pin.getPin(), MRAA_TEST_PIN, "Returned GPIO pin number is incorrect") + +if __name__ == '__main__': + u.main() diff --git a/tests/mock/gpio_checks_dir.py b/tests/mock/gpio_checks_dir.py new file mode 100755 index 0000000..eb89330 --- /dev/null +++ b/tests/mock/gpio_checks_dir.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +# Author: Alex Tereschenko +# Copyright (c) 2016 Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +MRAA_TEST_PIN = 0 + +class GpioChecksDir(u.TestCase): + def setUp(self): + self.pin = m.Gpio(MRAA_TEST_PIN) + + def tearDown(self): + del self.pin + + def test_set_dir_output(self): + direction = m.DIR_OUT + res = self.pin.dir(direction) + self.assertEqual(res, m.SUCCESS, "Setting GPIO to output failed") + self.assertEqual(self.pin.readDir(), direction, "GPIO has incorrect direction after dir(DIR_OUT)") + + def test_set_dir_output_HIGH(self): + res = self.pin.dir(m.DIR_OUT_HIGH) + self.assertEqual(res, m.SUCCESS, "Setting GPIO to output HIGH failed") + self.assertEqual(self.pin.readDir(), m.DIR_OUT, "GPIO has incorrect direction after dir(DIR_OUT_HIGH)") + self.assertEqual(self.pin.read(), 1, "GPIO has incorrect state after dir(DIR_OUT_HIGH)") + + def test_set_dir_output_LOW(self): + res = self.pin.dir(m.DIR_OUT_LOW) + self.assertEqual(res, m.SUCCESS, "Setting GPIO to output LOW failed") + self.assertEqual(self.pin.readDir(), m.DIR_OUT, "GPIO has incorrect direction after dir(DIR_OUT_LOW)") + self.assertEqual(self.pin.read(), 0, "GPIO has incorrect state after dir(DIR_OUT_LOW)") + + def test_set_dir_input(self): + direction = m.DIR_IN + res = self.pin.dir(direction) + self.assertEqual(res, m.SUCCESS, "Setting GPIO to input failed") + self.assertEqual(self.pin.readDir(), direction, "GPIO has incorrect direction after dir(DIR_IN)") + + def test_set_dir_invalid(self): + direction = 99 + res = self.pin.dir(direction) + self.assertNotEqual(res, m.SUCCESS, "Setting direction to " + str(direction) + " should have failed") + +if __name__ == '__main__': + u.main() diff --git a/tests/mock/gpio_checks_edge.py b/tests/mock/gpio_checks_edge.py new file mode 100755 index 0000000..10ea54e --- /dev/null +++ b/tests/mock/gpio_checks_edge.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +# Author: Alex Tereschenko +# Copyright (c) 2016 Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +MRAA_TEST_PIN = 0 + +class GpioChecksEdge(u.TestCase): + def setUp(self): + self.pin = m.Gpio(MRAA_TEST_PIN) + + def tearDown(self): + del self.pin + + def test_set_edge_mode_NONE(self): + res = self.pin.edge(m.EDGE_NONE) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting edge mode to EDGE_NONE did not return unimplemented") + + def test_set_edge_mode_BOTH(self): + res = self.pin.edge(m.EDGE_BOTH) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting edge mode to EDGE_BOTH did not return unimplemented") + + def test_set_edge_mode_RISING(self): + res = self.pin.edge(m.EDGE_RISING) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting edge mode to EDGE_RISING did not return unimplemented") + + def test_set_edge_mode_FALLING(self): + res = self.pin.edge(m.EDGE_FALLING) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting edge mode to EDGE_FALLING did not return unimplemented") + +if __name__ == '__main__': + u.main() diff --git a/tests/mock/gpio_checks_isr.py b/tests/mock/gpio_checks_isr.py new file mode 100644 index 0000000..cc43915 --- /dev/null +++ b/tests/mock/gpio_checks_isr.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +# Author: Alex Tereschenko +# Copyright (c) 2016 Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +MRAA_TEST_PIN = 0 + +def test_isr(): + print("In the ISR") + +class GpioChecksIsr(u.TestCase): + def setUp(self): + self.pin = m.Gpio(MRAA_TEST_PIN) + + def tearDown(self): + del self.pin + + def test_set_isr(self): + self.pin.dir(m.DIR_IN) + res = self.pin.isr(m.EDGE_BOTH, test_isr, None) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Enabling ISR did not return unimplemented") + + def test_isr_exit(self): + self.pin.dir(m.DIR_IN) + self.pin.isr(m.EDGE_BOTH, test_isr, None) + res = self.pin.isrExit() + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Calling isrExit() did not return unimplemented") + +if __name__ == '__main__': + u.main() diff --git a/tests/mock/gpio_checks_mode.py b/tests/mock/gpio_checks_mode.py new file mode 100644 index 0000000..5693053 --- /dev/null +++ b/tests/mock/gpio_checks_mode.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +# Author: Alex Tereschenko +# Copyright (c) 2016 Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +MRAA_TEST_PIN = 0 + +class GpioChecksMode(u.TestCase): + def setUp(self): + self.pin = m.Gpio(MRAA_TEST_PIN) + + def tearDown(self): + del self.pin + + def test_set_mode_STRONG(self): + res = self.pin.mode(m.MODE_STRONG) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting GPIO mode to MODE_STRONG did not return unimplemented") + + def test_set_mode_PULLUP(self): + res = self.pin.mode(m.MODE_PULLUP) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting GPIO mode to MODE_PULLUP did not return unimplemented") + + def test_set_mode_PULLDOWN(self): + res = self.pin.mode(m.MODE_PULLDOWN) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting GPIO mode to MODE_PULLDOWN did not return unimplemented") + + def test_set_mode_HIZ(self): + res = self.pin.mode(m.MODE_HIZ) + self.assertEqual(res, m.ERROR_FEATURE_NOT_IMPLEMENTED, "Setting GPIO mode to MODE_HIZ did not return unimplemented") + +if __name__ == '__main__': + u.main() diff --git a/tests/mock/gpio_checks_write_read.py b/tests/mock/gpio_checks_write_read.py new file mode 100755 index 0000000..ba50170 --- /dev/null +++ b/tests/mock/gpio_checks_write_read.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +# Author: Alex Tereschenko +# Copyright (c) 2016 Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +MRAA_TEST_PIN = 0 + +class GpioChecksWriteRead(u.TestCase): + def setUp(self): + self.pin = m.Gpio(MRAA_TEST_PIN) + + def tearDown(self): + del self.pin + + def test_gpio_as_output_write_HIGH(self): + self.pin.dir(m.DIR_OUT) + res = self.pin.write(1) + self.assertEqual(res, m.SUCCESS, "Setting GPIO to HIGH failed") + res = self.pin.read() + self.assertEqual(res, 1, "GPIO is not HIGH after write(1)") + + def test_gpio_as_output_write_LOW(self): + self.pin.dir(m.DIR_OUT) + res = self.pin.write(0) + self.assertEqual(res, m.SUCCESS, "Setting GPIO to LOW failed") + res = self.pin.read() + self.assertEqual(res, 0, "GPIO is not LOW after write(0)") + + def test_gpio_as_output_write_invalid(self): + self.pin.dir(m.DIR_OUT) + value = 10 + res = self.pin.write(value) + self.assertNotEqual(res, m.SUCCESS, "Writing " + str(value) + " to GPIO should have failed") + res = self.pin.read() + self.assertNotEqual(res, value, "Writing " + str(value) + " to GPIO should not have set it to " + str(value)) + + def test_gpio_as_input_write_HIGH(self): + self.pin.dir(m.DIR_IN) + res = self.pin.write(1) + self.assertNotEqual(res, m.SUCCESS, "Setting GPIO in INPUT to HIGH should have failed") + + def test_gpio_as_input_write_LOW(self): + self.pin.dir(m.DIR_IN) + res = self.pin.write(0) + self.assertNotEqual(res, m.SUCCESS, "Setting GPIO in INPUT to LOW should have failed") + +if __name__ == '__main__': + u.main() diff --git a/tests/mock/platform_checks.py b/tests/mock/platform_checks.py new file mode 100755 index 0000000..b37be26 --- /dev/null +++ b/tests/mock/platform_checks.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# Author: Costin Constantin +# Copyright (c) 2015 Intel Corporation. +# +# Contributors: Alex Tereschenko +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import mraa as m +import unittest as u + +PLATFORM_PINCOUNT = 1 +PLATFORM_STD_ADC_RES_BITS = 10 +PLATFORM_MAX_ADC_RES_BITS = 12 + +class PlatformChecks(u.TestCase): + def test_platform_pin_count(self): + self.assertEqual(m.getPinCount(), PLATFORM_PINCOUNT, "Wrong number of pins reported by platform") + + def test_adc_std_res(self): + adc_std_res = m.adcSupportedBits() + print("Platform ADC standard resolution is: " + str(adc_std_res) + " bits") + self.assertEqual(adc_std_res, PLATFORM_STD_ADC_RES_BITS, "Wrong ADC standard resolution") + + def test_adc_max_res(self): + adc_max_res = m.adcRawBits() + print("Platform ADC max. resolution is: " + str(adc_max_res) + " bits") + self.assertEqual(adc_max_res, PLATFORM_MAX_ADC_RES_BITS, "Wrong ADC max. resolution") + +if __name__ == "__main__": + u.main()