From 4a854156ed5057747310db40d8f806b16271e1c7 Mon Sep 17 00:00:00 2001 From: Cristian Heredia Date: Thu, 18 Aug 2022 21:12:18 -0700 Subject: [PATCH 1/4] Built test container environment --- docker-compose.yml | 13 +++++++++++++ test.Dockerfile | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 docker-compose.yml create mode 100644 test.Dockerfile diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..eb8b28c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +services: + rebalance-lnd: + container_name: rebalance-lnd + build: + context: . + dockerfile: test.Dockerfile + volumes: + - .:/code + working_dir: /code + environment: + - PYTHONDONTWRITEBYTECODE=1 + restart: unless-stopped + entrypoint: ["sleep", "infinity"] diff --git a/test.Dockerfile b/test.Dockerfile new file mode 100644 index 0000000..a6e9237 --- /dev/null +++ b/test.Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.10 + +ENV PIP_NO_CACHE_DIR=off \ + PIP_DISABLE_PIP_VERSION_CHECK=on + +COPY requirements.txt ./ + +# System deps: +RUN apt-get update && apt-get upgrade -y \ + # Clean cache: + && apt-get clean -y && rm -rf /var/lib/apt/lists/* \ + # Install python packages + && pip install -r requirements.txt From a88d799f5ae9267ed1ef673a133f2fd76ac1fe27 Mon Sep 17 00:00:00 2001 From: Cristian Heredia Date: Thu, 18 Aug 2022 21:29:34 -0700 Subject: [PATCH 2/4] Added test runner command --- Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..06413b1 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +up: ## Docker compose up, start container + docker compose up -d --build +down: ## Docker compose down + docker compose down --remove-orphans +shell: ## Shell into container + docker compose exec rebalance-lnd bash +test: ## Run tests + docker compose exec rebalance-lnd python -m unittest discover tests/ + +.PHONY: help +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.DEFAULT_GOAL := help From ddc8a3651cb983ee01eb63663376b437ef7e80c3 Mon Sep 17 00:00:00 2001 From: Cristian Heredia Date: Sat, 20 Aug 2022 14:00:50 -0700 Subject: [PATCH 3/4] Tested output.py functions --- Dockerfile | 18 +-- Makefile | 4 +- test.Dockerfile | 15 +- tests/unit/__init__.py | 0 tests/unit/test_output.py | 280 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 301 insertions(+), 16 deletions(-) create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/test_output.py diff --git a/Dockerfile b/Dockerfile index 6914289..0e43810 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,15 @@ FROM python:3.10-alpine3.14 RUN apk add --update --no-cache linux-headers gcc g++ git openssh-client \ - && apk add libstdc++ --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted \ - && git clone --depth=1 https://github.com/C-Otto/rebalance-lnd.git \ - && rm -rf rebalance-lnd/.github \ - && cd rebalance-lnd \ - && /usr/local/bin/python -m pip install --upgrade pip \ - && pip install -r requirements.txt \ - && cd / \ - && apk del linux-headers gcc g++ git openssh-client \ - && mkdir /root/.lnd + && apk add libstdc++ --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted \ + && git clone --depth=1 https://github.com/C-Otto/rebalance-lnd.git \ + && rm -rf rebalance-lnd/.github \ + && cd rebalance-lnd \ + && /usr/local/bin/python -m pip install --upgrade pip \ + && pip install -r requirements.txt \ + && cd / \ + && apk del linux-headers gcc g++ git openssh-client \ + && mkdir /root/.lnd VOLUME [ "/root/.lnd" ] diff --git a/Makefile b/Makefile index 06413b1..cdac711 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,9 @@ up: ## Docker compose up, start container down: ## Docker compose down docker compose down --remove-orphans shell: ## Shell into container - docker compose exec rebalance-lnd bash + docker compose exec rebalance-lnd sh test: ## Run tests - docker compose exec rebalance-lnd python -m unittest discover tests/ + docker compose exec rebalance-lnd python -m unittest discover tests/ -v .PHONY: help help: diff --git a/test.Dockerfile b/test.Dockerfile index a6e9237..e51d37a 100644 --- a/test.Dockerfile +++ b/test.Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10 +FROM python:3.10-alpine3.14 ENV PIP_NO_CACHE_DIR=off \ PIP_DISABLE_PIP_VERSION_CHECK=on @@ -6,8 +6,13 @@ ENV PIP_NO_CACHE_DIR=off \ COPY requirements.txt ./ # System deps: -RUN apt-get update && apt-get upgrade -y \ - # Clean cache: - && apt-get clean -y && rm -rf /var/lib/apt/lists/* \ +RUN apk add --update --no-cache \ + linux-headers \ + gcc \ + g++ \ + git openssh-client \ + && apk add libstdc++ --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted \ # Install python packages - && pip install -r requirements.txt + && pip install -r requirements.txt \ + # Remove system deps + && apk del linux-headers gcc g++ git openssh-client diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/test_output.py b/tests/unit/test_output.py new file mode 100644 index 0000000..789591b --- /dev/null +++ b/tests/unit/test_output.py @@ -0,0 +1,280 @@ +import unittest +from output import ( + format_alias, + format_ppm, + format_fee_msat, + format_fee_msat_red, + format_fee_msat_white, + format_fee_sat, + format_earning, + format_amount, + format_amount_green, + format_error, + print_bar, + format_boring_string, + format_success, + format_channel_id, + format_warning, +) + + +class TestFormat(unittest.TestCase): + def test_format_alias(self): + """Verifies format output""" + test_aliases = [ + ("utf-node", "\x1b[1mutf-node\x1b[22m"), + ("node", "\x1b[1mnode\x1b[22m"), + ("my-node", "\x1b[1mmy-node\x1b[22m"), + (1, "\x1b[1m1\x1b[22m"), + ("1", "\x1b[1m1\x1b[22m"), + (b"1", "\x1b[1mb'1'\x1b[22m"), + (True, "\x1b[1mTrue\x1b[22m"), + ("True", "\x1b[1mTrue\x1b[22m"), + (False, "\x1b[1mFalse\x1b[22m"), + ("False", "\x1b[1mFalse\x1b[22m"), + (None, "\x1b[1mNone\x1b[22m"), + ("None", "\x1b[1mNone\x1b[22m"), + ] + + for test_alias in test_aliases: + self.assertEqual(format_alias(test_alias[0]), test_alias[1]) + + def test_format_ppm(self): + """Verifies format output""" + test_cases = [ + (1000, None, "\x1b[1m1,000ppm\x1b[22m"), + (1000, 1, "\x1b[1m1,000ppm\x1b[22m"), + (1000, 10, "\x1b[1m 1,000ppm\x1b[22m"), + ] + + for test_case in test_cases: + ppm = test_case[0] + min_length = test_case[1] + output = test_case[2] + + self.assertEqual(format_ppm(ppm, min_length), output) + + def test_invalid_format_ppm(self): + """Observes behavior with string input""" + + with self.assertRaises(ValueError) as context: + ppm = "1000" + min_length = None + format_ppm(ppm, min_length) + + self.assertEqual(str(context.exception), "Cannot specify ',' with 's'.") + + def test_fee_msat(self): + """Verifies format output""" + test_cases = [ + (1000, None, "\x1b[36m1,000 mSAT\x1b[39m"), + (1000, 1, "\x1b[36m1,000 mSAT\x1b[39m"), + (1000, 10, "\x1b[36m 1,000 mSAT\x1b[39m"), + ] + + for test_case in test_cases: + ppm = test_case[0] + min_length = test_case[1] + output = test_case[2] + + self.assertEqual(format_fee_msat(ppm, min_length), output) + + def test_invalid_format_fee_msat(self): + """Observes behavior with string input""" + + with self.assertRaises(ValueError) as context: + ppm = "1000" + min_length = None + format_fee_msat(ppm, min_length) + + self.assertEqual(str(context.exception), "Cannot specify ',' with 's'.") + + def test_fee_msat_red(self): + """Verifies format output""" + test_cases = [ + (1000, None, "\x1b[31m1,000 mSAT\x1b[39m"), + (1000, 1, "\x1b[31m1,000 mSAT\x1b[39m"), + (1000, 10, "\x1b[31m 1,000 mSAT\x1b[39m"), + ] + + for test_case in test_cases: + ppm = test_case[0] + min_length = test_case[1] + output = test_case[2] + + self.assertEqual(format_fee_msat_red(ppm, min_length), output) + + def test_fee_msat_white(self): + """Verifies format output""" + test_cases = [ + (1000, None, "\x1b[97m1,000 mSAT\x1b[39m"), + (1000, 1, "\x1b[97m1,000 mSAT\x1b[39m"), + (1000, 10, "\x1b[97m 1,000 mSAT\x1b[39m"), + ] + + for test_case in test_cases: + ppm = test_case[0] + min_length = test_case[1] + output = test_case[2] + + self.assertEqual(format_fee_msat_white(ppm, min_length), output) + + def test_fee_sat(self): + """Verifies format output""" + test_cases = [ + (1000, "\x1b[36m1,000 sats\x1b[39m"), + (1, "\x1b[36m1 sats\x1b[39m"), + ] + + for test_case in test_cases: + fee_sat = test_case[0] + output = test_case[1] + + self.assertEqual(format_fee_sat(fee_sat), output) + + def test_format_earning(self): + """Verifies format output""" + test_cases = [ + (1000, None, "\x1b[32m1,000 mSAT\x1b[39m"), + (1000, 1, "\x1b[32m1,000 mSAT\x1b[39m"), + (1000, 10, "\x1b[32m 1,000 mSAT\x1b[39m"), + ] + + for test_case in test_cases: + msat = test_case[0] + min_width = test_case[1] + output = test_case[2] + + self.assertEqual(format_earning(msat, min_width), output) + + def test_format_amount(self): + """Verifies format output""" + test_cases = [ + (1000, None, "\x1b[33m1,000\x1b[39m"), + (1000, 1, "\x1b[33m1,000\x1b[39m"), + (1000, 10, "\x1b[33m 1,000\x1b[39m"), + ] + + for test_case in test_cases: + amount = test_case[0] + min_width = test_case[1] + output = test_case[2] + + self.assertEqual(format_amount(amount, min_width), output) + + def test_format_amount_green(self): + """Verifies format output""" + test_cases = [ + (1000, 1, "\x1b[32m1,000\x1b[39m"), + (1000, 10, "\x1b[32m 1,000\x1b[39m"), + ] + + for test_case in test_cases: + amount = test_case[0] + min_width = test_case[1] + output = test_case[2] + + self.assertEqual(format_amount_green(amount, min_width), output) + + def test_invalid_format_amount_green(self): + """Observes behavior with invalid min_width""" + + with self.assertRaises(ValueError) as context: + amount = "1000" + min_width = None + format_amount_green(amount, min_width) + + self.assertEqual(str(context.exception), "Invalid format specifier") + + def test_format_boring_string(self): + """Verifies format output""" + test_cases = [ + ("hello", "\x1b[40m\x1b[90mhello\x1b[39m\x1b[49m"), + ("world", "\x1b[40m\x1b[90mworld\x1b[39m\x1b[49m"), + (True, "\x1b[40m\x1b[90mTrue\x1b[39m\x1b[49m"), + (None, "\x1b[40m\x1b[90mNone\x1b[39m\x1b[49m"), + ] + + for test_case in test_cases: + string = test_case[0] + output = test_case[1] + + self.assertEqual(format_boring_string(string), output) + + def test_format_channel_id(self): + """Verifies format output""" + test_cases = [ + ("hello", "\x1b[40m\x1b[90mhello\x1b[39m\x1b[49m"), + ("world", "\x1b[40m\x1b[90mworld\x1b[39m\x1b[49m"), + (True, "\x1b[40m\x1b[90mTrue\x1b[39m\x1b[49m"), + (None, "\x1b[40m\x1b[90mNone\x1b[39m\x1b[49m"), + ] + + for test_case in test_cases: + string = test_case[0] + output = test_case[1] + + self.assertEqual(format_channel_id(string), output) + + def test_format_success(self): + """Verifies format output""" + test_cases = [ + ("hello", "\x1b[46m\x1b[97mhello\x1b[39m\x1b[49m"), + ("world", "\x1b[46m\x1b[97mworld\x1b[39m\x1b[49m"), + (True, "\x1b[46m\x1b[97mTrue\x1b[39m\x1b[49m"), + (None, "\x1b[46m\x1b[97mNone\x1b[39m\x1b[49m"), + ] + + for test_case in test_cases: + string = test_case[0] + output = test_case[1] + + self.assertEqual(format_success(string), output) + + def test_format_warning(self): + """Verifies format output""" + test_cases = [ + ("hello", "\x1b[33mhello\x1b[39m"), + ("world", "\x1b[33mworld\x1b[39m"), + (True, "\x1b[33mTrue\x1b[39m"), + (None, "\x1b[33mNone\x1b[39m"), + ] + + for test_case in test_cases: + string = test_case[0] + output = test_case[1] + + self.assertEqual(format_warning(string), output) + + def test_format_error(self): + """Verifies format output""" + test_cases = [ + ("hello", "\x1b[31mhello\x1b[39m"), + ("world", "\x1b[31mworld\x1b[39m"), + (True, "\x1b[31mTrue\x1b[39m"), + (None, "\x1b[31mNone\x1b[39m"), + ] + + for test_case in test_cases: + string = test_case[0] + output = test_case[1] + + self.assertEqual(format_error(string), output) + + def test_print_bar(self): + """Verifies format output""" + test_cases = [ + (1, 2, "\x1b[1m[\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m]\x1b[22m"), + ( + 1, + 10, + "\x1b[1m[\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m█\x1b[22m\x1b[1m]\x1b[22m", + ), + (10, 1, "\x1b[1m[\x1b[22m\x1b[1m█\x1b[22m░░░░░░░░░\x1b[1m]\x1b[22m"), + ] + + for test_case in test_cases: + width = test_case[0] + length = test_case[1] + output = test_case[2] + self.assertEqual(print_bar(width, length), output) From f099c75bdba5826f074c7df9d6a0ad594cfe5a24 Mon Sep 17 00:00:00 2001 From: Cristian Heredia Date: Sat, 20 Aug 2022 14:06:48 -0700 Subject: [PATCH 4/4] Added test README --- Dockerfile | 18 +++++++++--------- tests/README.md | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 tests/README.md diff --git a/Dockerfile b/Dockerfile index 0e43810..6914289 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,15 @@ FROM python:3.10-alpine3.14 RUN apk add --update --no-cache linux-headers gcc g++ git openssh-client \ - && apk add libstdc++ --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted \ - && git clone --depth=1 https://github.com/C-Otto/rebalance-lnd.git \ - && rm -rf rebalance-lnd/.github \ - && cd rebalance-lnd \ - && /usr/local/bin/python -m pip install --upgrade pip \ - && pip install -r requirements.txt \ - && cd / \ - && apk del linux-headers gcc g++ git openssh-client \ - && mkdir /root/.lnd + && apk add libstdc++ --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted \ + && git clone --depth=1 https://github.com/C-Otto/rebalance-lnd.git \ + && rm -rf rebalance-lnd/.github \ + && cd rebalance-lnd \ + && /usr/local/bin/python -m pip install --upgrade pip \ + && pip install -r requirements.txt \ + && cd / \ + && apk del linux-headers gcc g++ git openssh-client \ + && mkdir /root/.lnd VOLUME [ "/root/.lnd" ] diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..4b8da5b --- /dev/null +++ b/tests/README.md @@ -0,0 +1,22 @@ +# Running tests +1. To start the test environment container run: +```shell +make up +``` +2. Run tests +```shell +make test +``` +3. Bring down the docker compose environment +```shell +make down +``` + +If you need to shell into the docker container to run extra commands you can do so by running +```shell +make shell +``` +and then your command, e,g., +```shell +pip install black +```