From 01bd998ea835142a0277049e61ba06d8118a983c Mon Sep 17 00:00:00 2001 From: "C. Allwardt" Date: Tue, 27 Jul 2021 01:11:53 -0700 Subject: [PATCH] Added pytest for vctl workflows Added peerlist watcher debuging script. --- .github/workflows/pytest-vctl.yml | 114 ++++++++++++++++++++++++++++ debugging_utils/peerlist-watcher.py | 114 ++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 .github/workflows/pytest-vctl.yml create mode 100644 debugging_utils/peerlist-watcher.py diff --git a/.github/workflows/pytest-vctl.yml b/.github/workflows/pytest-vctl.yml new file mode 100644 index 0000000000..82ce928d22 --- /dev/null +++ b/.github/workflows/pytest-vctl.yml @@ -0,0 +1,114 @@ +--- +# This workflow is meant as a foundational workflow for running integration/unit tests on multiple targeted +# ubuntu versions with multiple python versions. +# +# This workflow utilizes the build-dependency-cache workflow which sets up the environment dependencies using +# bootstrap.py --all +# + +# Documentation for the syntax of this file is located +# https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions + +# The workflow name will show up in the action tab on github during execution +# https://github.com/VOLTTRON/volttron/actions (or if you are pushing to your own fork change the user) +name: Testing volttron-ctl + +# Determine what events are going to trigger a running of the workflow +on: [push, pull_request] + +jobs: + # The job named build + build: + # The strategy allows customization of the build and allows matrixing the version of os and software + # https://docs.github.com/en/free-pro-team@l.atest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategy + strategy: + fail-fast: false + matrix: + # Each entry in the os and python-version matrix will be run so for the 3 x 4 there will be 12 jobs run + os: [ ubuntu-16.04, ubuntu-18.04, ubuntu-20.04 ] + python-version: [ 3.6, 3.7] # , 3.8, 3.9 ] + + # Run-on determines the operating system available to run on + # - At the current time there is only ubuntu machines between 16.04 and 20.04 available + # - This uses the matrix os from the strategy above + runs-on: ${{ matrix.os }} + + # Each step will be run in order of listing. + steps: + # checkout the volttron repository and set current direectory to it + - uses: actions/checkout@v2 + + # Install erlang for rabbitmq + - name: Install erlang + if: matrix.os != 'ubuntu-20.04' + run: | + sudo scripts/rabbit_dependencies.sh debian ${{ matrix.os }} + + # setup the python environment for the operating system + - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + # Attempt to restore the cache from the build-dependency-cache workflow if present then + # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) + - name: Has restored cache + id: check_files + uses: andstor/file-existence-action@v1 + with: + files: "env/bin/activate" + + # This step is only run if the cache wasn't able to be restored. + - name: Install dependencies including rmq + if: steps.check_files.outputs.files_exists != 'true' && matrix.os != 'ubuntu-20.04' + run: | + pip install wheel + python bootstrap.py --all --rabbitmq --force + + - name: Install dependencies other than rmq + if: steps.check_files.outputs.files_exists != 'true' && matrix.os == 'ubuntu-20.04' + run: | + pip install wheel + python bootstrap.py --all --force + + - name: Install volttron + run: | + source env/bin/activate + pip install -e . + + # Run the specified tests and save the results to a unique file that can be archived for later analysis. + - name: Run pytest + run: | + source env/bin/activate + pip install pytest-rerunfailures + pip install -e . + pytest volttrontesting/platform/control_tests \ + -rf -o junit_family=xunit2 --junitxml=output/test-vctl-${{matrix.os}}-${{ matrix.python-version }}-results.xml + + # Archive the results from the pytest to storage. + - name: Archive test results + uses: actions/upload-artifact@v2 + if: always() + with: + name: pytest-report + path: output/test-vctl-${{matrix.os}}-${{ matrix.python-version }}-results.xml + +# - name: Publish Unit Test Results +# uses: EnricoMi/publish-unit-test-result-action@v1.5 +# if: always() +# with: +# github_token: ${{ secrets.WORKFLOW_ACCESS_TOKEN }} +# files: output/test-testutils*.xml + + +#-cov=com --cov-report=xml --cov-report=html +# pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html +# - name: Lint with flake8 +# run: | +# # stop the build if there are Python syntax errors or undefined names +# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics +# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide +# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics +# - name: Test with pytest +# run: | +# pytest --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html diff --git a/debugging_utils/peerlist-watcher.py b/debugging_utils/peerlist-watcher.py new file mode 100644 index 0000000000..e5b681438f --- /dev/null +++ b/debugging_utils/peerlist-watcher.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- {{{ +# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: +# +# Copyright 2020, Battelle Memorial Institute. +# +# 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. +# +# This material was prepared as an account of work sponsored by an agency of +# the United States Government. Neither the United States Government nor the +# United States Department of Energy, nor Battelle, nor any of their +# employees, nor any jurisdiction or organization that has cooperated in the +# development of these materials, makes any warranty, express or +# implied, or assumes any legal liability or responsibility for the accuracy, +# completeness, or usefulness or any information, apparatus, product, +# software, or process disclosed, or represents that its use would not infringe +# privately owned rights. Reference herein to any specific commercial product, +# process, or service by trade name, trademark, manufacturer, or otherwise +# does not necessarily constitute or imply its endorsement, recommendation, or +# favoring by the United States Government or any agency thereof, or +# Battelle Memorial Institute. The views and opinions of authors expressed +# herein do not necessarily state or reflect those of the +# United States Government or any agency thereof. +# +# PACIFIC NORTHWEST NATIONAL LABORATORY operated by +# BATTELLE for the UNITED STATES DEPARTMENT OF ENERGY +# under Contract DE-AC05-76RL01830 +# }}} + +""" +This script watches a temp file for volttron_home to change. When it changes, this +script will attempt to connect and execute peerlist on the platform after every +10th of a second. + +Execute the following in an activated shell: + + python debugging_utils/peerlist-watcher.py + +In another shell echo the volttron home to the proper file. + + +""" +import os +from pathlib import Path +from typing import Optional + +import gevent + +from volttron.platform.keystore import KeyStore +from volttron.platform.vip.agent import Agent +from volttron.platform.vip.agent.utils import build_agent + + +def get_volttron_home(): + if Path("/tmp/volttron_home.txt").exists(): + with open("/tmp/volttron_home.txt") as fp: + return fp.read().strip() + return None + + +def get_public_private_key(volttron_home): + ks = KeyStore() + return ks.public, ks.secret + + +volttron_home = get_volttron_home() +last_output = "" + +agent: Optional[Agent] = None +while True: + new_volttron_home = get_volttron_home() + if new_volttron_home is not None and new_volttron_home != volttron_home: + if agent: + agent.core.stop() + agent = None + volttron_home = new_volttron_home + + os.environ['VOLTTRON_HOME'] = volttron_home + public, secret = get_public_private_key(volttron_home) + last_output = f"Attempting connection {volttron_home}" + print(last_output) + agent = build_agent(volttron_home=volttron_home, + identity="peer.finder", + publickey=public, + secretkey=secret, + serverkey=public) + + if agent: + try: + with gevent.Timeout(5): + next_last_output = f"Peerlist: {agent.vip.peerlist().get()}" + if next_last_output != last_output: + last_output = next_last_output + print(last_output) + except gevent.Timeout: + agent.core.stop() + agent = None + else: + next_last_output = "waiting on file." + if next_last_output != last_output: + last_output = next_last_output + print(last_output) + + gevent.sleep(0.1) +