mirror of
https://github.com/geoserver/geoserver-cloud.git
synced 2025-12-08 20:16:08 +00:00
Add acceptance tests
This commit is contained in:
parent
cd03d921f7
commit
32f6a9b633
44
.github/workflows/build.yaml
vendored
44
.github/workflows/build.yaml
vendored
@ -23,25 +23,35 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Setup Java
|
# - name: Setup Java
|
||||||
uses: actions/setup-java@v2
|
# uses: actions/setup-java@v2
|
||||||
with:
|
# with:
|
||||||
distribution: 'temurin'
|
# distribution: 'temurin'
|
||||||
java-version: '21'
|
# java-version: '21'
|
||||||
cache: 'maven'
|
# cache: 'maven'
|
||||||
|
- name: Install CI dependencies
|
||||||
|
run: python3 -m pip install --user --requirement=ci/requirements.txt
|
||||||
|
|
||||||
- name: Validate source code formatting
|
# - name: Validate source code formatting
|
||||||
run: make lint
|
# run: make lint
|
||||||
|
|
||||||
- name: Build and test
|
# - name: Build and test
|
||||||
|
# run: |
|
||||||
|
# make install test
|
||||||
|
|
||||||
|
# - name: Build docker images
|
||||||
|
# run: |
|
||||||
|
# make build-image
|
||||||
|
|
||||||
|
- name: Run acceptance tests
|
||||||
run: |
|
run: |
|
||||||
make install test
|
make acceptance-tests
|
||||||
|
|
||||||
- name: Build docker images
|
- name: Print docker compose logs
|
||||||
run: |
|
run: (cd compose && c2cciutils-docker-logs)
|
||||||
make build-image
|
if: always()
|
||||||
|
|
||||||
- name: Remove project jars from cached repository
|
# - name: Remove project jars from cached repository
|
||||||
run: |
|
# run: |
|
||||||
rm -rf ~/.m2/repository/org/geoserver
|
# rm -rf ~/.m2/repository/org/geoserver
|
||||||
find ~/.m2/repository -name "*SNAPSHOT*" -type d | xargs rm -rf {}
|
# find ~/.m2/repository -name "*SNAPSHOT*" -type d | xargs rm -rf {}
|
||||||
|
|||||||
4
.github/workflows/pull-request.yaml
vendored
4
.github/workflows/pull-request.yaml
vendored
@ -47,6 +47,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make build-image
|
make build-image
|
||||||
|
|
||||||
|
- name: Run acceptance tests
|
||||||
|
run: |
|
||||||
|
make acceptance-tests
|
||||||
|
|
||||||
- name: Remove project jars from cached repository
|
- name: Remove project jars from cached repository
|
||||||
run: |
|
run: |
|
||||||
rm -rf ~/.m2/repository/org/geoserver
|
rm -rf ~/.m2/repository/org/geoserver
|
||||||
|
|||||||
18
Makefile
18
Makefile
@ -1,7 +1,13 @@
|
|||||||
all: install test build-image
|
all: install test build-image
|
||||||
|
|
||||||
TAG=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout`
|
TAG=$(shell mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
|
||||||
COSIGN_PASSWORD := $(COSIGN_PASSWORD)
|
COSIGN_PASSWORD := $(COSIGN_PASSWORD)
|
||||||
|
COMPOSE_PGCONFIG_OPTIONS ?= -f compose.yml -f catalog-pgconfig.yml
|
||||||
|
COMPOSE_DATADIR_OPTIONS ?= -f compose.yml -f catalog-datadir.yml
|
||||||
|
COMPOSE_ACCEPTANCE_PGCONFIG_OPTIONS ?= $(COMPOSE_PGCONFIG_OPTIONS) -f acceptance.yml
|
||||||
|
COMPOSE_ACCEPTANCE_DATADIR_OPTIONS ?= $(COMPOSE_DATADIR_OPTIONS) -f acceptance.yml
|
||||||
|
UID=$(shell id -u)
|
||||||
|
GID=$(shell id -g)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
./mvnw clean
|
./mvnw clean
|
||||||
@ -78,3 +84,13 @@ verify-image:
|
|||||||
fi; \
|
fi; \
|
||||||
done'
|
done'
|
||||||
|
|
||||||
|
.PHONY: build-acceptance
|
||||||
|
build-acceptance:
|
||||||
|
docker build --tag=acceptance:$(TAG) acceptance_tests
|
||||||
|
|
||||||
|
.PHONY: acceptance-tests
|
||||||
|
acceptance-tests:
|
||||||
|
acceptance-tests: build-acceptance
|
||||||
|
(cd compose/ && TAG=$(TAG) GS_USER=$(UID):$(GID) docker compose $(COMPOSE_ACCEPTANCE_DATADIR_OPTIONS) up -d)
|
||||||
|
sleep 30
|
||||||
|
(cd compose/ && TAG=$(TAG) GS_USER=$(UID):$(GID) docker compose $(COMPOSE_ACCEPTANCE_DATADIR_OPTIONS) exec -T acceptance pytest . -vvv --color=yes)
|
||||||
|
|||||||
3
acceptance_tests/.gitignore
vendored
Normal file
3
acceptance_tests/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# ignore all python cache files recursively
|
||||||
|
**/__pycache__/
|
||||||
|
poetry.lock
|
||||||
15
acceptance_tests/Dockerfile
Normal file
15
acceptance_tests/Dockerfile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
FROM ubuntu:24.04 AS base
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get upgrade --assume-yes \
|
||||||
|
&& apt-get install --assume-yes --no-install-recommends \
|
||||||
|
vim curl jq libmagic1 zip python3-pip libpq-dev python3-dev gcc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& rm /usr/lib/python*/EXTERNALLY-MANAGED
|
||||||
|
|
||||||
|
COPY . /acceptance_tests
|
||||||
|
|
||||||
|
WORKDIR /acceptance_tests
|
||||||
|
RUN python3 -m pip install --disable-pip-version-check .
|
||||||
|
|
||||||
|
CMD ["sleep", "infinity"]
|
||||||
18
acceptance_tests/README.md
Normal file
18
acceptance_tests/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# GeoServer Cloud acceptance tests
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
[Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```shell
|
||||||
|
poetry install
|
||||||
|
```
|
||||||
|
|
||||||
|
# Run the tests
|
||||||
|
First start the docker composition then run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
GEOSERVER_URL=http://localhost:9090/geoserver/cloud poetry run pytest -vvv .
|
||||||
|
```
|
||||||
17
acceptance_tests/pyproject.toml
Normal file
17
acceptance_tests/pyproject.toml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[tool.poetry]
|
||||||
|
name = "acceptance-tests"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "todo"
|
||||||
|
authors = ["todo"]
|
||||||
|
readme = "README.md"
|
||||||
|
packages = [{ include = "tests" }]
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.10"
|
||||||
|
pytest = "^8.3.3"
|
||||||
|
geoservercloud = "^0.2.5"
|
||||||
|
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
12
acceptance_tests/tests/conftest.py
Normal file
12
acceptance_tests/tests/conftest.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from geoservercloud import GeoServerCloud
|
||||||
|
|
||||||
|
|
||||||
|
GEOSERVER_URL = os.getenv("GEOSERVER_URL", "http://gateway:8080/geoserver/cloud")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def geoserver():
|
||||||
|
yield GeoServerCloud(GEOSERVER_URL)
|
||||||
140
acceptance_tests/tests/test_cascaded_stores.py
Normal file
140
acceptance_tests/tests/test_cascaded_stores.py
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from conftest import GEOSERVER_URL
|
||||||
|
from geoservercloud import GeoServerCloud
|
||||||
|
|
||||||
|
WORKSPACE = "test_cascade"
|
||||||
|
WMS_STORE = "test_cascaded_wms_store"
|
||||||
|
WMS_URL = "https://wms.geo.admin.ch/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities"
|
||||||
|
WMS_LAYER = "ch.swisstopo.swissboundaries3d-gemeinde-flaeche.fill"
|
||||||
|
WMTS_STORE = "test_cascaded_wmts_store"
|
||||||
|
WMTS_URL = "https://wmts.geo.admin.ch/EPSG/4326/1.0.0/WMTSCapabilities.xml"
|
||||||
|
WMTS_LAYER = "ch.swisstopo.pixelkarte-grau"
|
||||||
|
|
||||||
|
|
||||||
|
def create_cascaded_wms_store_payload():
|
||||||
|
return {
|
||||||
|
"wmsStore": {
|
||||||
|
"name": WMS_STORE,
|
||||||
|
"type": "WMS",
|
||||||
|
"enabled": "true",
|
||||||
|
"workspace": {"name": WORKSPACE},
|
||||||
|
"metadata": {"entry": {"@key": "useConnectionPooling", "$": "true"}},
|
||||||
|
"_default": "false",
|
||||||
|
"disableOnConnFailure": "false",
|
||||||
|
"capabilitiesURL": WMS_URL,
|
||||||
|
"maxConnections": 6,
|
||||||
|
"readTimeout": 60,
|
||||||
|
"connectTimeout": 30,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def delete_wms_store(geoserver):
|
||||||
|
geoserver.delete_request(
|
||||||
|
f"/rest/workspaces/{WORKSPACE}/wmsstores/{WMS_STORE}?recurse=true"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_wmts_store(geoserver):
|
||||||
|
geoserver.delete_request(
|
||||||
|
f"/rest/workspaces/{WORKSPACE}/wmtsstores/{WMTS_STORE}?recurse=true"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def geoserver():
|
||||||
|
geoserver = GeoServerCloud(url=GEOSERVER_URL)
|
||||||
|
geoserver.create_workspace(WORKSPACE, set_default_workspace=True)
|
||||||
|
geoserver.publish_workspace(WORKSPACE)
|
||||||
|
yield geoserver
|
||||||
|
# geoserver.delete_workspace(WORKSPACE)
|
||||||
|
|
||||||
|
|
||||||
|
def test_cascaded_wms(geoserver):
|
||||||
|
format = "image/jpeg"
|
||||||
|
|
||||||
|
# Create WMS store
|
||||||
|
payload = create_cascaded_wms_store_payload()
|
||||||
|
response = geoserver.post_request(
|
||||||
|
f"/rest/workspaces/{WORKSPACE}/wmsstores", json=payload
|
||||||
|
)
|
||||||
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
# Publish layer
|
||||||
|
payload = {
|
||||||
|
"wmsLayer": {
|
||||||
|
"name": WMS_LAYER,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response = geoserver.post_request(
|
||||||
|
f"/rest/workspaces/{WORKSPACE}/wmsstores/{WMS_STORE}/wmslayers",
|
||||||
|
json=payload,
|
||||||
|
)
|
||||||
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
# Perform GetMap request
|
||||||
|
response = geoserver.get_map(
|
||||||
|
layers=[WMS_LAYER],
|
||||||
|
bbox=(2590000, 1196000, 2605000, 1203000),
|
||||||
|
size=(10, 10),
|
||||||
|
format=format,
|
||||||
|
)
|
||||||
|
assert response.info().get("Content-Type") == format
|
||||||
|
|
||||||
|
# Perform GetFeatureInfo request
|
||||||
|
response = geoserver.get_feature_info(
|
||||||
|
layers=[WMS_LAYER],
|
||||||
|
bbox=(2599999.5, 1199999.5, 2600000.5, 1200000.5),
|
||||||
|
size=(40, 40),
|
||||||
|
info_format="application/json",
|
||||||
|
xy=(20, 20),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Due to conflicting formats, the forwarding of GetFeatureInfo requests from map.geo.admin (MapServer)
|
||||||
|
# through GeoServer is not possible as of 2.25.0.
|
||||||
|
# See https://sourceforge.net/p/geoserver/mailman/message/30757977/
|
||||||
|
data = json.loads(response.read().decode("utf-8"))
|
||||||
|
assert data.get("features") == []
|
||||||
|
|
||||||
|
delete_wms_store(geoserver)
|
||||||
|
|
||||||
|
|
||||||
|
def test_cascaded_wmts(geoserver):
|
||||||
|
format = "image/jpeg"
|
||||||
|
|
||||||
|
# Create WMTS store
|
||||||
|
response = geoserver.create_wmts_store(
|
||||||
|
WORKSPACE,
|
||||||
|
WMTS_STORE,
|
||||||
|
capabilities="https://wmts.geo.admin.ch/EPSG/4326/1.0.0/WMTSCapabilities.xml",
|
||||||
|
)
|
||||||
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
# Publish layer (GeoServer)
|
||||||
|
response = geoserver.create_wmts_layer(WORKSPACE, WMTS_STORE, WMTS_LAYER)
|
||||||
|
assert response.status_code == 201
|
||||||
|
response = geoserver.get_request(
|
||||||
|
f"/rest/workspaces/{WORKSPACE}/wmtsstores/{WMTS_STORE}/layers/{WMTS_LAYER}.json"
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
# Publish the layer in GWC
|
||||||
|
response = geoserver.publish_gwc_layer(WORKSPACE, WMTS_LAYER)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
# Perform GetTile request (GWC)
|
||||||
|
response = geoserver.get_tile(
|
||||||
|
layer=f"{WORKSPACE}:{WMTS_LAYER}",
|
||||||
|
tile_matrix_set="EPSG:4326",
|
||||||
|
tile_matrix="EPSG:4326:9",
|
||||||
|
row=122,
|
||||||
|
column=534,
|
||||||
|
format=format,
|
||||||
|
)
|
||||||
|
assert response.info().get("Content-Type") == format
|
||||||
|
|
||||||
|
response = geoserver.delete_request(f"/gwc/rest/layers/{WORKSPACE}:{WMTS_LAYER}")
|
||||||
|
assert response.status_code == 200
|
||||||
|
delete_wmts_store(geoserver)
|
||||||
23
acceptance_tests/tests/test_workspace.py
Normal file
23
acceptance_tests/tests/test_workspace.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
def test_create_get_and_delete_workspace(geoserver):
|
||||||
|
workspace = "test_create_workspace"
|
||||||
|
response = geoserver.create_workspace(workspace)
|
||||||
|
assert response.status_code == 201
|
||||||
|
response = geoserver.get_request(f"/rest/workspaces/{workspace}.json")
|
||||||
|
assert response.status_code == 200
|
||||||
|
response = geoserver.publish_workspace(workspace)
|
||||||
|
assert response.status_code == 200
|
||||||
|
response = geoserver.delete_workspace(workspace)
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_workspace(geoserver):
|
||||||
|
workspace = "update_workspace"
|
||||||
|
response = geoserver.create_workspace(workspace, isolated=True)
|
||||||
|
assert response.status_code == 201
|
||||||
|
response = geoserver.get_request(f"/rest/workspaces/{workspace}.json")
|
||||||
|
assert response.json().get("workspace").get("isolated") == True
|
||||||
|
response = geoserver.create_workspace(workspace, isolated=False)
|
||||||
|
assert response.status_code == 200
|
||||||
|
response = geoserver.get_request(f"/rest/workspaces/{workspace}.json")
|
||||||
|
assert response.json().get("workspace").get("isolated") == False
|
||||||
|
geoserver.delete_workspace(workspace)
|
||||||
1
ci/requirements.txt
Normal file
1
ci/requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
c2cciutils[checks]==1.6.18
|
||||||
95
compose/acceptance.yml
Normal file
95
compose/acceptance.yml
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
services:
|
||||||
|
acceptance:
|
||||||
|
image: acceptance:${TAG}
|
||||||
|
depends_on:
|
||||||
|
init-datadir:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
gateway:
|
||||||
|
condition: service_healthy
|
||||||
|
discovery:
|
||||||
|
condition: service_healthy
|
||||||
|
config:
|
||||||
|
condition: service_healthy
|
||||||
|
wms:
|
||||||
|
condition: service_healthy
|
||||||
|
# TODO: add wcs and wps
|
||||||
|
wfs:
|
||||||
|
condition: service_healthy
|
||||||
|
gwc:
|
||||||
|
condition: service_healthy
|
||||||
|
webui:
|
||||||
|
condition: service_started
|
||||||
|
rest:
|
||||||
|
condition: service_healthy
|
||||||
|
acl:
|
||||||
|
condition: service_started
|
||||||
|
|
||||||
|
# For github CI
|
||||||
|
acl:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
gateway:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
discovery:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
config:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
wms:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
healthcheck:
|
||||||
|
retries: 20
|
||||||
|
wfs:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
healthcheck:
|
||||||
|
retries: 20
|
||||||
|
rest:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
healthcheck:
|
||||||
|
retries: 20
|
||||||
|
gwc:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
healthcheck:
|
||||||
|
retries: 20
|
||||||
|
webui:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
|
rabbitmq:
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: "1.0"
|
||||||
|
memory: 512M
|
||||||
@ -8,6 +8,7 @@ volumes:
|
|||||||
type: none
|
type: none
|
||||||
o: bind
|
o: bind
|
||||||
device: $PWD/../config
|
device: $PWD/../config
|
||||||
|
driver: local
|
||||||
|
|
||||||
x-gs-dependencies: &gs-dependencies
|
x-gs-dependencies: &gs-dependencies
|
||||||
rabbitmq:
|
rabbitmq:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user