Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7284f165 authored by Arnau Vàzquez's avatar Arnau Vàzquez
Browse files

Merge branch 'functional_tests' into 'master'

Bootstrap functional tests

Closes e/qa/headquarter#100

See merge request !48
parents 97190b8b 811399da
Loading
Loading
Loading
Loading

.flake8

0 → 100644
+3 −0
Original line number Diff line number Diff line
[flake8]
max-line-length = 88
ignore = E203, E731
+53 −6
Original line number Diff line number Diff line
@@ -8,11 +8,10 @@ variables:
  PUBLISH_URL: ota.ecloud.global
  DOCKER_TLS_CERTDIR: "/certs"

services:
- docker:19.03.1-dind

build:
  stage: build
  services:
    - docker:19.03.1-dind
  script:
  - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME || true
  - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
@@ -21,6 +20,52 @@ build:
  - if [ "${CI_COMMIT_REF_NAME}" = master ] ; then docker push $CI_REGISTRY_IMAGE:latest ; fi
  tags:
    - generic_privileged
  rules:
    - if: '$CI_PIPELINE_SOURCE != "schedule"'

check:rules:tests:
  stage: build
  image: python:3.11-slim
  before_script:
    - pip install black==22.10.0 flake8==5.0.4 isort==5.10.1
  script:
    - cd tests/functional
    - black --check .
    - flake8 .
    - isort --check .
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - tests/functional/*

.tests:functional:
  stage: test
  image: python:3.11-slim
  variables:
    PYTEST_ADDOPTS: "--junitxml=report.xml"
  before_script:
    - cd tests/functional/
    - pip install -r requirements.txt
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - tests/functional/*
  artifacts:
    when: always
    reports:
      junit: tests/functional/report.xml


tests:functional:staging:
  extends: .tests:functional
  script:
    - pytest --ota-domain "test.${PUBLISH_URL}"

tests:functional:production:
  extends: .tests:functional
  script:
    - pytest --ota-domain "${PUBLISH_URL}"

# Deploy stage
.deploy:image:
@@ -44,6 +89,8 @@ build:

deploy:staging:
  extends: .deploy:image
  rules:
    - if: '$CI_COMMIT_REF_NAME != "production" && $CI_PIPELINE_SOURCE != "schedule"'
      when: manual
  environment:
    name: staging
@@ -51,8 +98,8 @@ deploy:staging:

deploy:production:
  extends: .deploy:image
  only:
    - production
  rules:
    - if: '$CI_COMMIT_REF_NAME == "production" && $CI_PIPELINE_SOURCE != "schedule"'
  environment:
    name: production
    url: https://ota.ecloud.global
+28 −0
Original line number Diff line number Diff line
import pytest


class Context:
    def __init__(self, config):
        self.domain = config.getoption("--ota-domain")
        assert self.domain is not None, "OTA server domain has to be defined"
        self.device = config.getoption("--ota-device")
        self.channel = config.getoption("--ota-channel")
        self.url = f"https://{self.domain}"


def pytest_addoption(parser):
    parser.addoption(
        "--ota-domain", action="store", default=None, help="OTA server domain"
    )
    parser.addoption(
        "--ota-device", action="store", default="FP3", help="OTA device name"
    )
    parser.addoption(
        "--ota-channel", action="store", default="stable", help="OTA channel name"
    )


@pytest.fixture
def ctx(request):
    context = Context(request.config)
    yield context
+2 −0
Original line number Diff line number Diff line
pytest==7.2.0
httpx==0.23.1
+69 −0
Original line number Diff line number Diff line
import httpx
import pytest


@pytest.fixture
def ctx(ctx):
    ctx.cli = httpx.Client(base_url=f"{ctx.url}/api/v1", timeout=60)
    yield ctx


def test_list_device_builds(ctx):
    res = ctx.cli.get(f"/{ctx.device}/{ctx.channel}")
    assert res.status_code == httpx.codes.OK
    data = res.json()
    assert not data["error"]
    assert len(data["response"])
    build = data["response"][-1]
    assert build["channel"] == ctx.channel
    assert build["romtype"] == ctx.channel
    assert build["url"].startswith(ctx.url)
    assert build["filename"].startswith("e-")


def test_list_build_with_incremental_update_field(ctx):
    # list and sort all builds by datetime
    res = ctx.cli.get(f"/{ctx.device}/{ctx.channel}")
    assert res.status_code == httpx.codes.OK
    data = sorted(res.json()["response"], key=lambda d: d["datetime"])
    assert len(data) >= 2

    # list build with incremental field
    build = data[-2]
    res = ctx.cli.get(f"/{ctx.device}/{ctx.channel}/{build['incremental']}")
    assert res.status_code == httpx.codes.OK
    data = res.json()
    assert len(data["response"]) == 1


def test_FP4_upgrade_from_given_build(ctx):
    """FP4 A12 upgrade is allowed only from 1.5-r build"""
    # create a map about /e/OS builds
    res = ctx.cli.get("/FP4/stable")
    assert res.status_code == httpx.codes.OK
    assert len(res.json()["response"])
    builds = {
        f"{d['version']}-{d['pre_version']}-{d['android_version']}": d
        for d in res.json()["response"]
    }

    # ensure that A12 builds are not listed with version <= 1.4-r
    build14r = builds["1.4--11"]
    res = ctx.cli.get(f"/FP4/stable/{build14r['incremental']}")
    assert res.status_code == httpx.codes.OK
    data = res.json()["response"]
    a12builds = [d for d in data if d["android_version"] == "12"]
    assert len(a12builds) == 0

    # ensure that A12 builds are listed with version == 1.5-r
    build15r = builds["1.5--11"]
    res = ctx.cli.get(
        f"/FP4/stable/{build15r['incremental']}",
        headers={"User-Agent": "eOS v1.5"},
    )
    assert res.status_code == httpx.codes.OK
    data = res.json()["response"]
    a12builds = [d for d in data if d["android_version"] == "12"]
    a11builds = [d for d in data if d["android_version"] == "11"]
    assert len(a11builds) == 0
    assert len(a12builds) >= 1