Skip to content

Commit 473f9d2

Browse files
committed
Modularize test and add more cases
1 parent b62a396 commit 473f9d2

File tree

7 files changed

+136
-131
lines changed

7 files changed

+136
-131
lines changed

client/.dockerignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ dropin.cache
99
*.pyo
1010
*.log
1111
*.pid
12-
*.db
1312
configure/*.local
1413

1514
*~

client/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ configure/*.local
1414
.*.swp
1515

1616
dbd
17-
db
1817

1918

2019
.iocsh_history

client/demoApp/Db/somerecords.db

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ record(longin, "$(P):li") {
88
record(longout, "$(P):lo") {
99
info("test", "testing")
1010
info("hello", "world")
11+
field(DESC, "testdesc")
1112
}

server/docker/config/cf1.conf

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,32 @@
33

44
[recceiver]
55

6-
# list of broadcast addresses.
7-
# default
8-
#addrlist = 255.255.255.255:5049
9-
# for local testing w/ firewall
10-
#addrlist = 127.255.255.255:5049
11-
12-
# Listen for TCP connections on this interface and port.
13-
# Port also used as source for UDP broadcasts.
14-
# Default uses wildcard address and a random port.
15-
#bind = 0.0.0.0:0
16-
176
# Processing chain
187
procs = cf
198

20-
# Time interval for sending recceiver advertisments
21-
#announceInterval = 15.0
22-
23-
# Idle Timeout for TCP connections.
24-
#tcptimeout = 15.0
25-
26-
# Time to wait before commiting updates
27-
# Doesn't effect IOC clients
28-
#commitInterval = 5.0
29-
30-
# Maximum concurrent "active" clients
31-
# to allow.
32-
#maxActive = 20
33-
349
# The channelFinder client is configuration information is
3510
# stored in /etc/channelfinderapi.conf as described in the client
3611
loglevel=DEBUG
12+
3713
[cf]
3814
# a space-separated list of infotags to set as CF Properties
39-
infotags = archive foo bar blah
15+
infotags = archive
16+
4017
# List environment variables that should be written as channel finder properties
4118
#
4219
# Comma-separated list of VARIABLE:PropertyName,
4320
# specifying which environment VARIABLEs to pass on to the channel finder
4421
# and defining the corresponding PropertyName
4522
#environment_vars=ENGINEER:Engineer,EPICS_BASE:EpicsVersion,PWD:WorkingDirectory
23+
4624
# Turn on optional alias and recordType properties
47-
#alias = on
48-
#recordType = on
49-
#recordDesc = on
25+
alias = on
26+
recordType = on
27+
recordDesc = on
5028

5129
# Mark all channels as 'Inactive' when processor is started (default: True)
5230
cleanOnStart = True
5331

54-
recceiverID = recc1
55-
findSizeLimit = 10000
56-
5732
[DEFAULT]
5833
BaseURL = http://cf:8080/ChannelFinder
5934
username = admin

server/docker/config/cf2.conf

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,9 @@
33

44
[recceiver]
55

6-
# list of broadcast addresses.
7-
# default
8-
#addrlist = 255.255.255.255:5049
9-
# for local testing w/ firewall
10-
#addrlist = 127.255.255.255:5049
11-
12-
# Listen for TCP connections on this interface and port.
13-
# Port also used as source for UDP broadcasts.
14-
# Default uses wildcard address and a random port.
15-
#bind = 0.0.0.0:0
16-
176
# Processing chain
187
procs = cf
198

20-
# Time interval for sending recceiver advertisments
21-
#announceInterval = 15.0
22-
23-
# Idle Timeout for TCP connections.
24-
#tcptimeout = 15.0
25-
26-
# Time to wait before commiting updates
27-
# Doesn't effect IOC clients
28-
#commitInterval = 5.0
29-
30-
# Maximum concurrent "active" clients
31-
# to allow.
32-
#maxActive = 20
33-
349
# The channelFinder client is configuration information is
3510
# stored in /etc/channelfinderapi.conf as described in the client
3611
loglevel=DEBUG
@@ -45,18 +20,15 @@ loglevel=DEBUG
4520
# and defining the corresponding PropertyName
4621
#environment_vars=ENGINEER:Engineer,EPICS_BASE:EpicsVersion,PWD:WorkingDirectory
4722
# Turn on optional alias and recordType properties
48-
#alias = on
49-
#recordType = on
50-
#recordDesc = on
23+
alias = on
24+
recordType = on
25+
recordDesc = on
5126

5227
# Mark all channels as 'Inactive' when processor is stopped (default: True)
5328
#cleanOnStop = True
5429
# Mark all channels as 'Inactive' when processor is started (default: True)
5530
cleanOnStart = True
5631

57-
recceiverID = recc2
58-
findSizeLimit = 10000
59-
6032
[DEFAULT]
6133
BaseURL = http://cf:8080/ChannelFinder
6234
username = admin

server/tests/docker.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import logging
2+
import pytest
3+
from testcontainers.compose import DockerCompose
4+
5+
from docker import DockerClient
6+
import pathlib
7+
8+
LOG: logging.Logger = logging.getLogger(__name__)
9+
10+
11+
def fullSetupDockerCompose() -> DockerCompose:
12+
current_path = pathlib.Path(__file__).parent.resolve()
13+
14+
return DockerCompose(
15+
str(current_path.parent.resolve()),
16+
compose_file_name=str(
17+
current_path.parent.joinpath("docker-compose.yml").resolve()
18+
),
19+
build=True,
20+
)
21+
22+
23+
def log_container_logs(compose: DockerCompose) -> None:
24+
docker_client = DockerClient()
25+
conts = {container.ID: container for container in compose.get_containers()}
26+
for cont_id, cont in conts.items():
27+
log = docker_client.containers.get(cont_id).logs()
28+
LOG.debug("Info for container %s", cont)
29+
LOG.debug("Logs for container %s", cont.Name)
30+
LOG.debug(log.decode("utf-8"))
31+
32+
33+
@pytest.fixture(scope="class")
34+
def setup_compose():
35+
LOG.info("Setup test environment")
36+
compose = fullSetupDockerCompose()
37+
compose.start()
38+
yield compose
39+
LOG.info("Teardown test environment")
40+
LOG.info("Stopping docker compose")
41+
if LOG.level <= logging.DEBUG:
42+
log_container_logs(compose)
43+
compose.stop()

server/tests/test_e2e.py

Lines changed: 82 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import pathlib
21
import time
3-
from docker import DockerClient
4-
from testcontainers.compose import DockerCompose
2+
import pytest
53

64
from channelfinder import ChannelFinderClient
75
import logging
6+
from .docker import setup_compose # noqa: F401
87

98
logging.basicConfig(
109
level=logging.DEBUG,
@@ -15,79 +14,96 @@
1514
LOG: logging.Logger = logging.getLogger(__name__)
1615

1716
MAX_WAIT_SECONDS = 180
18-
EXPECTED_DEFAULT_CHANNELS = 24
17+
EXPECTED_DEFAULT_CHANNELS = 32
1918

2019

21-
def fullSetupDockerCompose() -> DockerCompose:
22-
current_path = pathlib.Path(__file__).parent.resolve()
20+
def check_channel_count(cf_client, name="*", expected_count=EXPECTED_DEFAULT_CHANNELS):
21+
channels = cf_client.find(name="*")
22+
LOG.info("Found %s channels", len(channels))
23+
return len(channels) == expected_count
2324

24-
return DockerCompose(
25-
str(current_path.parent.resolve()),
26-
compose_file_name=str(
27-
current_path.parent.joinpath("docker-compose.yml").resolve()
28-
),
29-
build=True,
30-
)
25+
26+
def wait_for_sync(cf_client, check):
27+
seconds_to_wait = 1
28+
total_seconds_waited = 0
29+
while total_seconds_waited < MAX_WAIT_SECONDS:
30+
try:
31+
if check(cf_client):
32+
break
33+
except Exception as e:
34+
LOG.error(e)
35+
time.sleep(seconds_to_wait)
36+
total_seconds_waited += seconds_to_wait
37+
seconds_to_wait += 2
38+
39+
40+
def create_client_and_wait(compose):
41+
LOG.info("Waiting for channels to sync")
42+
cf_client = create_client_from_compose(compose)
43+
wait_for_sync(cf_client, lambda cf_client: check_channel_count(cf_client))
44+
return cf_client
45+
46+
47+
def create_client_from_compose(compose):
48+
cf_host, cf_port = compose.get_service_host_and_port("cf")
49+
cf_url = f"http://{cf_host if cf_host else 'localhost'}:{cf_port}/ChannelFinder"
50+
# wait for channels to sync
51+
LOG.info("CF URL: %s", cf_url)
52+
cf_client = ChannelFinderClient(BaseURL=cf_url)
53+
return cf_client
54+
55+
56+
@pytest.fixture(scope="class")
57+
def cf_client(setup_compose): # noqa: F811
58+
return create_client_and_wait(setup_compose)
3159

3260

3361
class TestE2E:
34-
compose: DockerCompose
35-
36-
def setup_method(self) -> None:
37-
"""Setup the test environment"""
38-
LOG.info("Setting up test")
39-
self.compose = fullSetupDockerCompose()
40-
self.compose.start()
41-
42-
def teardown_method(self) -> None:
43-
"""Teardown the test environment"""
44-
45-
LOG.info("Tearing down test")
46-
if self.compose:
47-
LOG.info("Stopping docker compose")
48-
if LOG.level <= logging.DEBUG:
49-
docker_client = DockerClient()
50-
conts = {
51-
container.ID: container
52-
for container in self.compose.get_containers()
53-
}
54-
for cont_id, cont in conts.items():
55-
log = docker_client.containers.get(cont_id).logs()
56-
LOG.debug("Info for container %s", cont)
57-
LOG.debug("Logs for container %s", cont.Name)
58-
LOG.debug(log.decode("utf-8"))
59-
self.compose.stop()
60-
61-
def test_smoke(self) -> None:
62+
def test_smoke(self, cf_client) -> None:
6263
"""
6364
Test that the setup in the docker compose creates channels in channelfinder
6465
"""
65-
LOG.info("Waiting for channels to sync")
66-
cf_host, cf_port = self.compose.get_service_host_and_port("cf")
67-
cf_url = f"http://{cf_host if cf_host else 'localhost'}:{cf_port}/ChannelFinder"
68-
# wait for channels to sync
69-
LOG.info("CF URL: %s", cf_url)
70-
cf_client = ChannelFinderClient(BaseURL=cf_url)
71-
self.wait_for_sync(cf_client)
7266
channels = cf_client.find(name="*")
7367
assert len(channels) == EXPECTED_DEFAULT_CHANNELS
7468
assert channels[0]["name"] == "IOC1-1::li"
7569

76-
def wait_for_sync(self, cf_client):
77-
seconds_to_wait = 1
78-
total_seconds_waited = 0
79-
while total_seconds_waited < MAX_WAIT_SECONDS:
80-
try:
81-
channels = cf_client.find(name="*")
82-
LOG.info(
83-
"Found %s in %s seconds",
84-
len(channels),
85-
total_seconds_waited,
86-
)
87-
if len(channels) == EXPECTED_DEFAULT_CHANNELS:
88-
break
89-
except Exception as e:
90-
LOG.error(e)
91-
time.sleep(seconds_to_wait)
92-
total_seconds_waited += seconds_to_wait
93-
seconds_to_wait += 2
70+
# Smoke Test Default Properties
71+
def test_alias(self, cf_client) -> None:
72+
"""
73+
Test that the setup in the docker compose creates channels with aliases in channelfinder
74+
"""
75+
channels = cf_client.find(property=[("alias", "*")])
76+
assert len(channels) == 8
77+
assert channels[0]["name"] == "IOC1-1:lix1"
78+
assert {
79+
"name": "alias",
80+
"value": "IOC1-1::li",
81+
"owner": "admin",
82+
"channels": [],
83+
} in channels[0]["properties"]
84+
85+
def test_desc(self, cf_client) -> None:
86+
"""
87+
Test that the setup in the docker compose creates channels with descriptions in channelfinder
88+
"""
89+
channels = cf_client.find(property=[("recordDesc", "*")])
90+
assert len(channels) == 4
91+
assert {
92+
"name": "recordDesc",
93+
"value": "testdesc",
94+
"owner": "admin",
95+
"channels": [],
96+
} in channels[0]["properties"]
97+
98+
def test_type(self, cf_client) -> None:
99+
"""
100+
Test that the setup in the docker compose creates channels with types in channelfinder
101+
"""
102+
channels = cf_client.find(property=[("recordType", "*")])
103+
assert len(channels) == EXPECTED_DEFAULT_CHANNELS
104+
assert {
105+
"name": "recordType",
106+
"value": "longin",
107+
"owner": "admin",
108+
"channels": [],
109+
} in channels[0]["properties"]

0 commit comments

Comments
 (0)