Browse Source

Merge pull request #1951 from mcspr/test/build-opts

Test: add an ability to run only one build configuration + fix related gcc warnings
master
Max Prokhorov 5 years ago
committed by GitHub
parent
commit
75ceae799e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 198 additions and 61 deletions
  1. +3
    -0
      .bandit
  2. +1
    -1
      .travis.yml
  3. +1
    -1
      code/espurna/crash.ino
  4. +15
    -7
      code/espurna/light.ino
  5. +4
    -3
      code/espurna/sensor.ino
  6. +0
    -1
      code/espurna/sensors/ADE7953Sensor.h
  7. +1
    -1
      code/espurna/sensors/EmonADS1X15Sensor.h
  8. +9
    -3
      code/espurna/sensors/PMSX003Sensor.h
  9. +0
    -1
      code/espurna/sensors/SI7021Sensor.h
  10. +21
    -0
      code/scripts/espurna_utils/__init__.py
  11. +9
    -3
      code/scripts/espurna_utils/display.py
  12. +133
    -0
      code/scripts/test_build.py
  13. +0
    -0
      code/test/build/extra/secure_client.h
  14. +0
    -39
      code/test_build.sh
  15. +1
    -1
      travis_script.sh

+ 3
- 0
.bandit View File

@ -0,0 +1,3 @@
# Ignore B404 "Avoid importing subprocess"
# Ignore B603 "Subprocess without shell equals true"
skips: ['B404', 'B603']

+ 1
- 1
.travis.yml View File

@ -26,7 +26,7 @@ jobs:
- stage: Test - stage: Test
env: BUILDER_ENV=travis-2_3_0 env: BUILDER_ENV=travis-2_3_0
- env: BUILDER_ENV=travis-latest - env: BUILDER_ENV=travis-latest
- env: BUILDER_ENV=travis-git BUILDER_EXTRA=secure_client
- env: BUILDER_ENV=travis-git BUILDER_EXTRA="-a test/build/extra/secure_client.h"
- stage: Release - stage: Release
env: BUILDER_THREAD=0 env: BUILDER_THREAD=0
- env: BUILDER_THREAD=1 - env: BUILDER_THREAD=1


+ 1
- 1
code/espurna/crash.ino View File

@ -190,7 +190,7 @@ void crashSetup() {
// Minumum of 16 and align for column formatter in crashDump() // Minumum of 16 and align for column formatter in crashDump()
// Maximum of flash sector size minus reserved space at the beginning // Maximum of flash sector size minus reserved space at the beginning
const uint16_t trace_max = constrain( const uint16_t trace_max = constrain(
((getSetting("sysTraceMax", SAVE_CRASH_STACK_TRACE_MAX).toInt() + 15) & -16),
abs((getSetting("sysTraceMax", SAVE_CRASH_STACK_TRACE_MAX).toInt() + 15) & -16),
0, (SPI_FLASH_SEC_SIZE - crashUsedSpace()) 0, (SPI_FLASH_SEC_SIZE - crashUsedSpace())
); );


+ 15
- 7
code/espurna/light.ino View File

@ -1172,6 +1172,10 @@ void _lightAPISetup() {
#if TERMINAL_SUPPORT #if TERMINAL_SUPPORT
void _lightChannelDebug(unsigned char id) {
DEBUG_MSG_P(PSTR("Channel #%u (%s): %d\n"), id, lightDesc(id).c_str(), lightChannel(id));
}
void _lightInitCommands() { void _lightInitCommands() {
terminalRegisterCommand(F("BRIGHTNESS"), [](Embedis* e) { terminalRegisterCommand(F("BRIGHTNESS"), [](Embedis* e) {
@ -1184,14 +1188,17 @@ void _lightInitCommands() {
}); });
terminalRegisterCommand(F("CHANNEL"), [](Embedis* e) { terminalRegisterCommand(F("CHANNEL"), [](Embedis* e) {
if (e->argc < 2) {
terminalError(F("CHANNEL <ID> [<VALUE>]"));
return;
if (!lightChannels()) return;
auto id = -1;
if (e->argc > 1) {
id = String(e->argv[1]).toInt();
} }
const int id = String(e->argv[1]).toInt();
if (id < 0 || id >= lightChannels()) {
terminalError(F("Channel value out of range"));
if (id < 0 || id >= static_cast<decltype(id)>(lightChannels())) {
for (unsigned char index = 0; index < lightChannels(); ++index) {
_lightChannelDebug(index);
}
return; return;
} }
@ -1200,7 +1207,8 @@ void _lightInitCommands() {
lightUpdate(true, true); lightUpdate(true, true);
} }
DEBUG_MSG_P(PSTR("Channel #%u (%s): %d\n"), id, lightDesc(id).c_str(), lightChannel(id));
_lightChannelDebug(id);
terminalOK(); terminalOK();
}); });


+ 4
- 3
code/espurna/sensor.ino View File

@ -238,6 +238,7 @@ void _sensorWebSocketOnConnected(JsonObject& root) {
for (unsigned char i=0; i<_sensors.size(); i++) { for (unsigned char i=0; i<_sensors.size(); i++) {
BaseSensor * sensor = _sensors[i]; BaseSensor * sensor = _sensors[i];
UNUSED(sensor);
#if EMON_ANALOG_SUPPORT #if EMON_ANALOG_SUPPORT
if (sensor->getID() == SENSOR_EMON_ANALOG_ID) { if (sensor->getID() == SENSOR_EMON_ANALOG_ID) {
@ -1378,17 +1379,17 @@ void _sensorConfigure() {
double value; double value;
HLW8012Sensor * sensor = (HLW8012Sensor *) _sensors[i]; HLW8012Sensor * sensor = (HLW8012Sensor *) _sensors[i];
if (value = getSetting("pwrExpectedC", 0).toFloat()) {
if ((value = getSetting("pwrExpectedC", 0).toFloat())) {
sensor->expectedCurrent(value); sensor->expectedCurrent(value);
setSetting("pwrRatioC", sensor->getCurrentRatio()); setSetting("pwrRatioC", sensor->getCurrentRatio());
} }
if (value = getSetting("pwrExpectedV", 0).toInt()) {
if ((value = getSetting("pwrExpectedV", 0).toInt())) {
sensor->expectedVoltage(value); sensor->expectedVoltage(value);
setSetting("pwrRatioV", sensor->getVoltageRatio()); setSetting("pwrRatioV", sensor->getVoltageRatio());
} }
if (value = getSetting("pwrExpectedP", 0).toInt()) {
if ((value = getSetting("pwrExpectedP", 0).toInt())) {
sensor->expectedPower(value); sensor->expectedPower(value);
setSetting("pwrRatioP", sensor->getPowerRatio()); setSetting("pwrRatioP", sensor->getPowerRatio());
} }


+ 0
- 1
code/espurna/sensors/ADE7953Sensor.h View File

@ -93,7 +93,6 @@ class ADE7953Sensor : public I2CSensor {
void pre() { void pre() {
uint32_t active_power1 = 0; uint32_t active_power1 = 0;
uint32_t active_power2 = 0; uint32_t active_power2 = 0;
uint32_t current_rms = 0;
uint32_t current_rms1 = 0; uint32_t current_rms1 = 0;
uint32_t current_rms2 = 0; uint32_t current_rms2 = 0;
uint32_t voltage_rms = 0; uint32_t voltage_rms = 0;


+ 1
- 1
code/espurna/sensors/EmonADS1X15Sensor.h View File

@ -327,7 +327,7 @@ class EmonADS1X15Sensor : public EmonSensor {
unsigned int readADC(unsigned char channel) { unsigned int readADC(unsigned char channel) {
UNUSED(channel); UNUSED(channel);
unsigned int value = i2c_read_uint16(_address, ADS1X15_REG_POINTER_CONVERT); unsigned int value = i2c_read_uint16(_address, ADS1X15_REG_POINTER_CONVERT);
if (_type = ADS1X15_CHIP_ADS1015) value >>= ADS1015_BIT_SHIFT;
if (_type == ADS1X15_CHIP_ADS1015) value >>= ADS1015_BIT_SHIFT;
delayMicroseconds(500); delayMicroseconds(500);
return value; return value;
} }


+ 9
- 3
code/espurna/sensors/PMSX003Sensor.h View File

@ -158,14 +158,13 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Public // Public
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
PMSX003Sensor(): BaseSensor() { PMSX003Sensor(): BaseSensor() {
_count = pms_specs[_type].slot_count; _count = pms_specs[_type].slot_count;
_sensor_id = SENSOR_PMSX003_ID; _sensor_id = SENSOR_PMSX003_ID;
} }
~PMSX003Sensor() { ~PMSX003Sensor() {
if (_serial) delete _serial;
removeSerial();
} }
void setRX(unsigned char pin_rx) { void setRX(unsigned char pin_rx) {
@ -216,7 +215,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
if (!_dirty) return; if (!_dirty) return;
if (_soft) { if (_soft) {
if (_serial) delete _serial;
if (_serial) removeSerial();
_serial = new SoftwareSerial(_pin_rx, _pin_tx, false, 64); _serial = new SoftwareSerial(_pin_rx, _pin_tx, false, 64);
static_cast<SoftwareSerial*>(_serial)->enableIntTx(false); static_cast<SoftwareSerial*>(_serial)->enableIntTx(false);
} }
@ -358,6 +357,13 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
return _slot_values[index]; return _slot_values[index];
} }
private:
void removeSerial() {
if (_serial && _soft) {
delete static_cast<SoftwareSerial*>(_serial);
}
}
protected: protected:
bool _soft = true; bool _soft = true;
unsigned int _pin_rx; unsigned int _pin_rx;


+ 0
- 1
code/espurna/sensors/SI7021Sensor.h View File

@ -147,7 +147,6 @@ class SI7021Sensor : public I2CSensor {
// When not using clock stretching (*_NOHOLD commands) delay here // When not using clock stretching (*_NOHOLD commands) delay here
// is needed to wait for the measurement. // is needed to wait for the measurement.
// According to datasheet the max. conversion time is ~22ms // According to datasheet the max. conversion time is ~22ms
unsigned long start = millis();
nice_delay(50); nice_delay(50);
// Clear the last to bits of LSB to 00. // Clear the last to bits of LSB to 00.


+ 21
- 0
code/scripts/espurna_utils/__init__.py View File

@ -1,3 +1,24 @@
# coding=utf-8
#
# Original extra_scripts.py
# Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#
# ldscripts, lwip patching, updated postmortem flags and git support
# Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .checks import check_cppcheck, check_printsize from .checks import check_cppcheck, check_printsize
from .float_support import remove_float_support from .float_support import remove_float_support
from .ldscripts import ldscripts_inject_libpath from .ldscripts import ldscripts_inject_libpath


+ 9
- 3
code/scripts/espurna_utils/display.py View File

@ -1,10 +1,11 @@
from __future__ import print_function from __future__ import print_function
import os
import sys import sys
import click
class Color(object): class Color(object):
BOLD = "\x1b[1;1m"
BLACK = "\x1b[1;30m" BLACK = "\x1b[1;30m"
RED = "\x1b[1;31m" RED = "\x1b[1;31m"
GREEN = "\x1b[1;32m" GREEN = "\x1b[1;32m"
@ -31,8 +32,13 @@ def print_warning(message, color=Color.LIGHT_YELLOW):
print(clr(color, message), file=sys.stderr) print(clr(color, message), file=sys.stderr)
def print_filler(fill, color=Color.WHITE, err=False):
width, _ = click.get_terminal_size()
def print_filler(fill, color=Color.WHITE, err=False, width_default=80):
width = width_default
try:
width = int(os.environ["COLUMNS"])
except (KeyError, ValueError):
pass
if len(fill) > 1: if len(fill) > 1:
fill = fill[0] fill = fill[0]


+ 133
- 0
code/scripts/test_build.py View File

@ -0,0 +1,133 @@
#!/usr/bin/env python
#
# Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
import time
import glob
import argparse
import atexit
import subprocess
import os
import sys
import datetime
from espurna_utils.display import Color, clr, print_warning
CUSTOM_HEADER = "espurna/config/custom.h"
if os.path.exists(CUSTOM_HEADER):
raise SystemExit(
clr(
Color.YELLOW,
"{} already exists, please run this script in a git-worktree(1) or a separate directory".format(
CUSTOM_HEADER
),
)
)
def try_remove(path):
try:
os.remove(path)
except: # pylint: disable=bare-except
print_warning("Please manually remove the file `{}`".format(path))
atexit.register(try_remove, CUSTOM_HEADER)
def main(args):
configurations = []
if not args.no_default:
configurations = list(glob.glob(args.default_configurations))
configurations.extend(x for x in (args.add or []))
if not configurations:
raise SystemExit(clr(Color.YELLOW, "No configurations selected"))
print(clr(Color.BOLD, "> Selected configurations:"))
for cfg in configurations:
print(cfg)
if args.list:
return
if not args.environment:
raise SystemExit(clr(Color.YELLOW, "No environment selected"))
print(clr(Color.BOLD, "> Selected environment: {}".format(args.environment)))
for cfg in configurations:
print(clr(Color.BOLD, "> Building {}".format(cfg)))
with open(CUSTOM_HEADER, "w") as custom_h:
def write(line):
sys.stdout.write(line)
custom_h.write(line)
name, _ = os.path.splitext(cfg)
name = os.path.basename(name)
write('#define MANUFACTURER "TEST_BUILD"\n')
write('#define DEVICE "{}"\n'.format(name.upper()))
with open(cfg, "r") as cfg_file:
for line in cfg_file:
write(line)
os_env = os.environ.copy()
os_env["PLATFORMIO_SRC_BUILD_FLAGS"] = "-DUSE_CUSTOM_H"
os_env["PLATFORMIO_BUILD_CACHE_DIR"] = "test/pio_cache"
cmd = ["platformio", "run", "-s", "-e", args.environment]
start = time.time()
subprocess.check_call(cmd, env=os_env)
end = time.time()
print(
clr(
Color.BOLD,
"> {}: {} bytes, {}".format(
cfg,
os.stat(
os.path.join(".pio", "build", args.environment, "firmware.bin")
).st_size,
datetime.timedelta(seconds=(end - start)),
),
)
)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"-l", "--list", action="store_true", help="List selected configurations"
)
parser.add_argument(
"-n",
"--no-default",
action="store_true",
help="Do not use default configurations (--default-configurations=...)",
)
parser.add_argument(
"-a",
"--add",
action="append",
help="Add path to selected configurations (can specify multiple times)",
)
parser.add_argument("-e", "--environment", help="PIO environment")
parser.add_argument(
"--default-configurations",
default="test/build/*.h",
help="(glob) default configuration headers",
)
main(parser.parse_args())

code/test/build/secure_client.h → code/test/build/extra/secure_client.h View File


+ 0
- 39
code/test_build.sh View File

@ -1,39 +0,0 @@
#!/bin/bash
set -eu -o pipefail
CUSTOM_HEADER="espurna/config/custom.h"
TARGET_ENVIRONMENT=${1:?"pio env name"}
shift 1
CONFIGURATIONS=(
basic
sensor
emon
light_my92xx
light_dimmer
nondefault
)
if [ $# > 0 ] ; then
CONFIGURATIONS=("${CONFIGURATIONS[@]}" "$@")
fi
trap 'rm -f ${CUSTOM_HEADER}' EXIT
for cfg in "${CONFIGURATIONS[@]}" ; do
echo "travis_fold:start:build_${cfg}"
echo "- building ${cfg}"
printf "#define MANUFACTURER \"%s\"\n" "TEST_BUILD" \
| tee ${CUSTOM_HEADER}
printf "#define DEVICE \"%s\"\n" "${cfg^^}" \
| tee --append ${CUSTOM_HEADER}
tee --append ${CUSTOM_HEADER} < "test/build/${cfg}.h"
export PLATFORMIO_SRC_BUILD_FLAGS="-DUSE_CUSTOM_H"
export PLATFORMIO_BUILD_CACHE_DIR="test/pio_cache"
time pio run -s -e "$TARGET_ENVIRONMENT"
echo "travis_fold:end:build_${cfg}"
done

+ 1
- 1
travis_script.sh View File

@ -5,7 +5,7 @@ set -e -v
cd code cd code
if [ ${TRAVIS_BUILD_STAGE_NAME} = "Test" ]; then if [ ${TRAVIS_BUILD_STAGE_NAME} = "Test" ]; then
./test_build.sh $BUILDER_ENV $BUILDER_EXTRA
scripts/test_build.py -e $BUILDER_ENV $BUILDER_EXTRA
else else
./build.sh -p ./build.sh -p
fi fi

Loading…
Cancel
Save