mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-01 13:23:01 +02:00
Merge pull request #1184 from kernelkit/releng
Release prep for v25.08.1
This commit is contained in:
@@ -39,7 +39,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Regression Test ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.name || inputs.name }} ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.target || inputs.target }}
|
name: Regression Test ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.name || inputs.name }} ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.target || inputs.target }}
|
||||||
runs-on: [ self-hosted, regression ]
|
runs-on: [self-hosted, regression]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout infix repo
|
- name: Checkout infix repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -87,7 +87,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
make test
|
make test
|
||||||
|
|
||||||
- name: Publish Test Result for ${{ env.TARGET }}
|
- name: Publish Test Result for ${{ env.TARGET }}
|
||||||
# Ensure this runs even if Regression Test fails
|
# Ensure this runs even if Regression Test fails
|
||||||
if: always()
|
if: always()
|
||||||
run: cat $TEST_PATH/.log/last/result-gh.md >> $GITHUB_STEP_SUMMARY
|
run: cat $TEST_PATH/.log/last/result-gh.md >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -96,15 +96,10 @@ jobs:
|
|||||||
# Ensure this runs even if Regression Test fails
|
# Ensure this runs even if Regression Test fails
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
asciidoctor-pdf \
|
make test-dir="$(pwd)/$TEST_PATH" test-report
|
||||||
--theme $TEST_PATH/9pm/report/theme.yml \
|
|
||||||
-a pdf-fontsdir=$TEST_PATH/9pm/report/fonts \
|
|
||||||
$TEST_PATH/.log/last/report.adoc \
|
|
||||||
-o $TEST_PATH/.log/last/report.pdf
|
|
||||||
|
|
||||||
- name: Upload Test Report as Artifact
|
- name: Upload Test Report as Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: test-report
|
name: test-report
|
||||||
path: ${{ env.TEST_PATH }}/.log/last/report.pdf
|
path: output/images/test-report.pdf
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,6 @@ jobs:
|
|||||||
name: "infix"
|
name: "infix"
|
||||||
|
|
||||||
test-publish-x86_64:
|
test-publish-x86_64:
|
||||||
if: startsWith(github.repository, 'kernelkit/')
|
if: ${{ github.repository_owner == 'kernelkit' && github.ref_name == 'main' }}
|
||||||
needs: test-run-x86_64
|
needs: test-run-x86_64
|
||||||
uses: ./.github/workflows/publish.yml
|
uses: ./.github/workflows/publish.yml
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ genboot()
|
|||||||
{
|
{
|
||||||
if [ -d "$bootdata" ]; then
|
if [ -d "$bootdata" ]; then
|
||||||
bootimg=$(cat <<EOF
|
bootimg=$(cat <<EOF
|
||||||
image efi-part.vfat {
|
image $BINARIES_DIR/efi-part.vfat {
|
||||||
size = $bootsize
|
size = $bootsize
|
||||||
vfat {
|
vfat {
|
||||||
file EFI {
|
file EFI {
|
||||||
@@ -98,7 +98,7 @@ EOF
|
|||||||
offset = $bootoffs
|
offset = $bootoffs
|
||||||
partition-type-uuid = U
|
partition-type-uuid = U
|
||||||
bootable = true
|
bootable = true
|
||||||
image = efi-part.vfat
|
image = $BINARIES_DIR/efi-part.vfat
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
)
|
)
|
||||||
|
|||||||
+3
-3
@@ -3,7 +3,7 @@ Change Log
|
|||||||
|
|
||||||
All notable changes to the project are documented in this file.
|
All notable changes to the project are documented in this file.
|
||||||
|
|
||||||
[v25.08.1][] - 2025-09-30
|
[v25.08.1][] - 2025-10-03
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
@@ -12,8 +12,8 @@ All notable changes to the project are documented in this file.
|
|||||||
### Fixes
|
### Fixes
|
||||||
- Fix #1150: `show-legacy` wrapper permissions
|
- Fix #1150: `show-legacy` wrapper permissions
|
||||||
- Fix #1155: `show ospf` commands regression
|
- Fix #1155: `show ospf` commands regression
|
||||||
- Fix #1169: Expected neighbors not shown in sysrepocfg
|
- Fix #1169: Expected OSPF neighbors not shown in `sysrepocfg` when the
|
||||||
- Various test stability improvments
|
system has at least one non-OSPF interface
|
||||||
|
|
||||||
[v25.08.0][] - 2025-09-01
|
[v25.08.0][] - 2025-09-01
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
=== OSPF Basic
|
=== OSPF Basic
|
||||||
==== Description
|
==== Description
|
||||||
Very basic OSPF test just test that OSPF sends HELLO packets between the DUTs
|
Verifies basic OSPF functionality by configuring two routers (R1 and R2)
|
||||||
and that they exchange routes, ending with a simple connectivity check.
|
with OSPF on their interconnecting link. The test ensures OSPF
|
||||||
|
neighbors are established, routes are exchanged between the routers, and
|
||||||
|
end-to-end connectivity is achieved.
|
||||||
|
|
||||||
|
An end-device (HOST) is connected to R2 on an interface without OSPF enabled.
|
||||||
|
This verifies that OSPF status information remains accessible when a router
|
||||||
|
has non-OSPF interfaces.
|
||||||
|
|
||||||
==== Topology
|
==== Topology
|
||||||
ifdef::topdoc[]
|
ifdef::topdoc[]
|
||||||
@@ -19,6 +25,7 @@ endif::topdoc[]
|
|||||||
. Set up topology and attach to target DUTs
|
. Set up topology and attach to target DUTs
|
||||||
. Configure targets
|
. Configure targets
|
||||||
. Wait for OSPF routes
|
. Wait for OSPF routes
|
||||||
|
. Verify R2 OSPF neighbors with non-OSPF interface
|
||||||
. Test connectivity from PC:data to 192.168.200.1
|
. Test connectivity from PC:data to 192.168.200.1
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""OSPF Basic
|
||||||
OSPF Basic
|
|
||||||
|
Verifies basic OSPF functionality by configuring two routers (R1 and R2)
|
||||||
|
with OSPF on their interconnecting link. The test ensures OSPF
|
||||||
|
neighbors are established, routes are exchanged between the routers, and
|
||||||
|
end-to-end connectivity is achieved.
|
||||||
|
|
||||||
|
An end-device (HOST) is connected to R2 on an interface without OSPF enabled.
|
||||||
|
This verifies that OSPF status information remains accessible when a router
|
||||||
|
has non-OSPF interfaces.
|
||||||
|
|
||||||
Very basic OSPF test just test that OSPF sends HELLO packets between the DUTs
|
|
||||||
and that they exchange routes, ending with a simple connectivity check.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# TODO: Remove HOST node once Infamy supports unconnected ports in topologies
|
||||||
|
|
||||||
import infamy
|
import infamy
|
||||||
import infamy.route as route
|
import infamy.route as route
|
||||||
from infamy.util import until, parallel
|
from infamy.util import until, parallel
|
||||||
|
|
||||||
|
|
||||||
def config_target1(target, data, link):
|
def config_target1(target, data, link):
|
||||||
target.put_config_dict("ietf-interfaces", {
|
target.put_config_dict("ietf-interfaces", {
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
@@ -30,8 +39,8 @@ def config_target1(target, data, link):
|
|||||||
"ipv4": {
|
"ipv4": {
|
||||||
"forwarding": True,
|
"forwarding": True,
|
||||||
"address": [{
|
"address": [{
|
||||||
"ip": "192.168.50.1",
|
"ip": "192.168.50.1",
|
||||||
"prefix-length": 24
|
"prefix-length": 24
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -40,8 +49,8 @@ def config_target1(target, data, link):
|
|||||||
"enabled": True,
|
"enabled": True,
|
||||||
"ipv4": {
|
"ipv4": {
|
||||||
"address": [{
|
"address": [{
|
||||||
"ip": "192.168.100.1",
|
"ip": "192.168.100.1",
|
||||||
"prefix-length": 32
|
"prefix-length": 32
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,38 +65,34 @@ def config_target1(target, data, link):
|
|||||||
target.put_config_dict("ietf-routing", {
|
target.put_config_dict("ietf-routing", {
|
||||||
"routing": {
|
"routing": {
|
||||||
"control-plane-protocols": {
|
"control-plane-protocols": {
|
||||||
"control-plane-protocol": [
|
"control-plane-protocol": [{
|
||||||
{
|
"type": "infix-routing:static",
|
||||||
"type": "infix-routing:static",
|
"name": "default",
|
||||||
"name": "default",
|
"static-routes": {
|
||||||
"static-routes": {
|
"ipv4": {
|
||||||
"ipv4": {
|
"route": [{
|
||||||
"route": [{
|
"destination-prefix": "192.168.33.1/32",
|
||||||
"destination-prefix": "192.168.33.1/32",
|
"next-hop": {
|
||||||
"next-hop": {
|
"special-next-hop": "blackhole"
|
||||||
"special-next-hop": "blackhole"
|
}
|
||||||
}
|
}]
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
{
|
}, {
|
||||||
"type": "infix-routing:ospfv2",
|
"type": "infix-routing:ospfv2",
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"ospf": {
|
"ospf": {
|
||||||
"redistribute": {
|
"redistribute": {
|
||||||
"redistribute": [{
|
"redistribute": [{
|
||||||
"protocol": "static"
|
"protocol": "static"
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
"protocol": "connected"
|
"protocol": "connected"
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
"areas": {
|
"areas": {
|
||||||
"area": [{
|
"area": [{
|
||||||
"area-id": "0.0.0.0",
|
"area-id": "0.0.0.0",
|
||||||
"interfaces":
|
"interfaces": {
|
||||||
{
|
|
||||||
"interface": [{
|
"interface": [{
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"name": link,
|
"name": link,
|
||||||
@@ -103,35 +108,43 @@ def config_target1(target, data, link):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
def config_target2(target, link):
|
|
||||||
|
def config_target2(target, link, data):
|
||||||
target.put_config_dict("ietf-interfaces", {
|
target.put_config_dict("ietf-interfaces", {
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
"interface": [
|
"interface": [{
|
||||||
{
|
"name": link,
|
||||||
"name": link,
|
"enabled": True,
|
||||||
"enabled": True,
|
"ipv4": {
|
||||||
"ipv4": {
|
"forwarding": True,
|
||||||
"forwarding": True,
|
"address": [{
|
||||||
"address": [{
|
"ip": "192.168.50.2",
|
||||||
"ip": "192.168.50.2",
|
"prefix-length": 24
|
||||||
"prefix-length": 24
|
}]
|
||||||
}]
|
}
|
||||||
}
|
}, {
|
||||||
},
|
"name": data,
|
||||||
{
|
"enabled": True,
|
||||||
"name": "lo",
|
"ipv4": {
|
||||||
"enabled": True,
|
"forwarding": True,
|
||||||
"forwarding": True,
|
"address": [{
|
||||||
"ipv4": {
|
"ip": "192.168.60.1",
|
||||||
"address": [{
|
"prefix-length": 24
|
||||||
"ip": "192.168.200.1",
|
}]
|
||||||
"prefix-length": 32
|
}
|
||||||
}]
|
}, {
|
||||||
}
|
"name": "lo",
|
||||||
}
|
"enabled": True,
|
||||||
]
|
"forwarding": True,
|
||||||
}
|
"ipv4": {
|
||||||
})
|
"address": [{
|
||||||
|
"ip": "192.168.200.1",
|
||||||
|
"prefix-length": 32
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
target.put_config_dict("ietf-system", {
|
target.put_config_dict("ietf-system", {
|
||||||
"system": {
|
"system": {
|
||||||
@@ -141,8 +154,7 @@ def config_target2(target, link):
|
|||||||
target.put_config_dict("ietf-routing", {
|
target.put_config_dict("ietf-routing", {
|
||||||
"routing": {
|
"routing": {
|
||||||
"control-plane-protocols": {
|
"control-plane-protocols": {
|
||||||
"control-plane-protocol": [
|
"control-plane-protocol": [{
|
||||||
{
|
|
||||||
"type": "infix-routing:ospfv2",
|
"type": "infix-routing:ospfv2",
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"ospf": {
|
"ospf": {
|
||||||
@@ -154,7 +166,7 @@ def config_target2(target, link):
|
|||||||
"areas": {
|
"areas": {
|
||||||
"area": [{
|
"area": [{
|
||||||
"area-id": "0.0.0.0",
|
"area-id": "0.0.0.0",
|
||||||
"interfaces":{
|
"interfaces": {
|
||||||
"interface": [{
|
"interface": [{
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"name": link,
|
"name": link,
|
||||||
@@ -165,31 +177,61 @@ def config_target2(target, link):
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}]
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def config_host(target, link):
|
||||||
|
target.put_config_dict("ietf-interfaces", {
|
||||||
|
"interfaces": {
|
||||||
|
"interface": [{
|
||||||
|
"name": link,
|
||||||
|
"enabled": True,
|
||||||
|
"ipv4": {
|
||||||
|
"address": [{
|
||||||
|
"ip": "192.168.60.2",
|
||||||
|
"prefix-length": 24
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
target.put_config_dict("ietf-system", {
|
||||||
|
"system": {
|
||||||
|
"hostname": "HOST"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
with infamy.Test() as test:
|
with infamy.Test() as test:
|
||||||
with test.step("Set up topology and attach to target DUTs"):
|
with test.step("Set up topology and attach to target DUTs"):
|
||||||
env = infamy.Env()
|
env = infamy.Env()
|
||||||
R1 = env.attach("R1", "mgmt")
|
R1 = env.attach("R1", "mgmt")
|
||||||
R2 = env.attach("R2", "mgmt")
|
R2 = env.attach("R2", "mgmt")
|
||||||
|
HOST = env.attach("HOST", "mgmt")
|
||||||
|
|
||||||
with test.step("Configure targets"):
|
with test.step("Configure targets"):
|
||||||
_, R1data = env.ltop.xlate("R1", "data")
|
_, R1data = env.ltop.xlate("R1", "data")
|
||||||
_, R2link = env.ltop.xlate("R2", "link")
|
_, R2link = env.ltop.xlate("R2", "link")
|
||||||
_, R1link= env.ltop.xlate("R1", "link")
|
_, R1link = env.ltop.xlate("R1", "link")
|
||||||
|
_, R2data = env.ltop.xlate("R2", "data")
|
||||||
|
_, HOSTlink = env.ltop.xlate("HOST", "link")
|
||||||
|
|
||||||
parallel(config_target1(R1, R1data, R1link),
|
parallel(config_target1(R1, R1data, R1link),
|
||||||
config_target2(R2, R2link))
|
config_target2(R2, R2link, R2data),
|
||||||
|
config_host(HOST, HOSTlink))
|
||||||
with test.step("Wait for OSPF routes"):
|
with test.step("Wait for OSPF routes"):
|
||||||
print("Waiting for OSPF routes..")
|
|
||||||
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||||
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||||
until(lambda: route.ipv4_route_exist(R2, "192.168.33.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
until(lambda: route.ipv4_route_exist(R2, "192.168.33.1/32", proto="ietf-ospf:ospfv2"), attempts=200)
|
||||||
|
|
||||||
|
with test.step("Verify R2 OSPF neighbors with non-OSPF interface"):
|
||||||
|
# Regression test for #1169
|
||||||
|
assert route.ospf_has_neighbors(R2)
|
||||||
|
|
||||||
with test.step("Test connectivity from PC:data to 192.168.200.1"):
|
with test.step("Test connectivity from PC:data to 192.168.200.1"):
|
||||||
_, hport0 = env.ltop.xlate("PC", "data")
|
_, hport0 = env.ltop.xlate("PC", "data")
|
||||||
with infamy.IsolatedMacVlan(hport0) as ns0:
|
with infamy.IsolatedMacVlan(hport0) as ns0:
|
||||||
|
|||||||
@@ -8,26 +8,34 @@ graph "2x2" {
|
|||||||
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
|
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
|
||||||
|
|
||||||
PC [
|
PC [
|
||||||
label="PC | { <mgmt1> mgmt1 | <data> data | <mgmt2> mgmt2 }",
|
label="PC | { <mgmt1> mgmt1 | <data> data | <mgmt2> mgmt2 | <mgmt3> mgmt3 }",
|
||||||
pos="20,80!",
|
pos="20,30!",
|
||||||
requires="controller",
|
requires="controller",
|
||||||
];
|
];
|
||||||
|
|
||||||
R1 [
|
R1 [
|
||||||
label="{ <mgmt> mgmt | <data> data | <link> link} | R1 \n 192.168.100.1/32 \n(lo)",
|
label="{ <mgmt> mgmt | <data> data | <link> link} | R1 \n 192.168.100.1/32 \n(lo)",
|
||||||
pos="250,80!",
|
pos="160,60!",
|
||||||
|
|
||||||
requires="infix",
|
requires="infix",
|
||||||
];
|
];
|
||||||
R2 [
|
R2 [
|
||||||
label="{ <link> link | <mgmt> mgmt | <data> data } | R2 \n 192.168.200.1/32 \n(lo)",
|
label="{ <link> link | <mgmt> mgmt | <data> data } | R2 \n 192.168.200.1/32 \n(lo)",
|
||||||
pos="250,30!",
|
pos="160,30!",
|
||||||
|
|
||||||
requires="infix",
|
requires="infix",
|
||||||
];
|
];
|
||||||
|
HOST [
|
||||||
|
label="{ <link> link | <mgmt> mgmt } | HOST \n end-device",
|
||||||
|
pos="153,0!",
|
||||||
|
|
||||||
|
requires="infix",
|
||||||
|
];
|
||||||
|
|
||||||
PC:mgmt1 -- R1:mgmt [requires="mgmt", color="lightgray"]
|
PC:mgmt1 -- R1:mgmt [requires="mgmt", color="lightgray"]
|
||||||
PC:mgmt2 -- R2:mgmt [requires="mgmt", color="lightgray"]
|
PC:mgmt2 -- R2:mgmt [requires="mgmt", color="lightgray"]
|
||||||
PC:data -- R1:data [color="black", headlabel="192.168.10.1/24", taillabel="192.168.10.2/24", fontcolor="black"]
|
PC:mgmt3 -- HOST:mgmt [requires="mgmt", color="lightgray"]
|
||||||
|
PC:data -- R1:data [color="black", headlabel="192.168.10.1/24", taillabel="192.168.10.2/24", labeldistance=6, fontcolor="black"]
|
||||||
R1:link -- R2:link [headlabel="192.168.50.2/24", taillabel="192.168.50.1/24", labeldistance=1, fontcolor="black", color="black"]
|
R1:link -- R2:link [headlabel="192.168.50.2/24", taillabel="192.168.50.1/24", labeldistance=1, fontcolor="black", color="black"]
|
||||||
|
R2:data -- HOST:link [headlabel="192.168.60.2/24", taillabel="192.168.60.1/24", labeldistance=1, fontcolor="black", color="black"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,74 +3,99 @@
|
|||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
|
||||||
<!-- Title: 2x2 Pages: 1 -->
|
<!-- Title: 2x2 Pages: 1 -->
|
||||||
<svg width="713pt" height="198pt"
|
<svg width="720pt" height="306pt"
|
||||||
viewBox="0.00 0.00 713.06 198.01" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
viewBox="0.00 0.00 720.00 306.08" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 194.01)">
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 302.52)">
|
||||||
<title>2x2</title>
|
<title>2x2</title>
|
||||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-194.01 709.06,-194.01 709.06,4 -4,4"/>
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-302.52 717.06,-302.52 717.06,4 -4,4"/>
|
||||||
<!-- PC -->
|
<!-- PC -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
<title>PC</title>
|
<title>PC</title>
|
||||||
<polygon fill="none" stroke="black" points="0,-120.51 0,-189.51 91,-189.51 91,-120.51 0,-120.51"/>
|
<polygon fill="none" stroke="black" points="0,-97.51 0,-189.51 91,-189.51 91,-97.51 0,-97.51"/>
|
||||||
<text text-anchor="middle" x="16.5" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">PC</text>
|
<text text-anchor="middle" x="16.5" y="-139.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">PC</text>
|
||||||
<polyline fill="none" stroke="black" points="33,-120.51 33,-189.51 "/>
|
<polyline fill="none" stroke="black" points="33,-97.51 33,-189.51 "/>
|
||||||
<text text-anchor="middle" x="62" y="-174.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
|
<text text-anchor="middle" x="62" y="-174.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt1</text>
|
||||||
<polyline fill="none" stroke="black" points="33,-166.51 91,-166.51 "/>
|
<polyline fill="none" stroke="black" points="33,-166.51 91,-166.51 "/>
|
||||||
<text text-anchor="middle" x="62" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
<text text-anchor="middle" x="62" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||||
<polyline fill="none" stroke="black" points="33,-143.51 91,-143.51 "/>
|
<polyline fill="none" stroke="black" points="33,-143.51 91,-143.51 "/>
|
||||||
<text text-anchor="middle" x="62" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
|
<text text-anchor="middle" x="62" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="33,-120.51 91,-120.51 "/>
|
||||||
|
<text text-anchor="middle" x="62" y="-105.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt3</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- R1 -->
|
<!-- R1 -->
|
||||||
<g id="node2" class="node">
|
<g id="node2" class="node">
|
||||||
<title>R1</title>
|
<title>R1</title>
|
||||||
<polygon fill="none" stroke="black" points="490.06,-120.51 490.06,-189.51 705.06,-189.51 705.06,-120.51 490.06,-120.51"/>
|
<polygon fill="none" stroke="black" points="498.06,-229.02 498.06,-298.02 713.06,-298.02 713.06,-229.02 498.06,-229.02"/>
|
||||||
<text text-anchor="middle" x="515.06" y="-174.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
<text text-anchor="middle" x="523.06" y="-282.82" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||||
<polyline fill="none" stroke="black" points="490.06,-166.51 540.06,-166.51 "/>
|
<polyline fill="none" stroke="black" points="498.06,-275.02 548.06,-275.02 "/>
|
||||||
<text text-anchor="middle" x="515.06" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
<text text-anchor="middle" x="523.06" y="-259.82" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||||
<polyline fill="none" stroke="black" points="490.06,-143.51 540.06,-143.51 "/>
|
<polyline fill="none" stroke="black" points="498.06,-252.02 548.06,-252.02 "/>
|
||||||
<text text-anchor="middle" x="515.06" y="-128.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
<text text-anchor="middle" x="523.06" y="-236.82" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||||
<polyline fill="none" stroke="black" points="540.06,-120.51 540.06,-189.51 "/>
|
<polyline fill="none" stroke="black" points="548.06,-229.02 548.06,-298.02 "/>
|
||||||
<text text-anchor="middle" x="622.56" y="-166.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1 </text>
|
<text text-anchor="middle" x="630.56" y="-274.82" font-family="DejaVu Sans Mono, Book" font-size="14.00">R1 </text>
|
||||||
<text text-anchor="middle" x="622.56" y="-151.31" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 192.168.100.1/32 </text>
|
<text text-anchor="middle" x="630.56" y="-259.82" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 192.168.100.1/32 </text>
|
||||||
<text text-anchor="middle" x="622.56" y="-136.31" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
<text text-anchor="middle" x="630.56" y="-244.82" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- PC--R1 -->
|
<!-- PC--R1 -->
|
||||||
<g id="edge1" class="edge">
|
<g id="edge1" class="edge">
|
||||||
<title>PC:mgmt1--R1:mgmt</title>
|
<title>PC:mgmt1--R1:mgmt</title>
|
||||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-178.01C91.5,-178.01 489.56,-178.01 489.56,-178.01"/>
|
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-178.51C91.5,-178.51 497.56,-286.52 497.56,-286.52"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- PC--R1 -->
|
<!-- PC--R1 -->
|
||||||
<g id="edge3" class="edge">
|
<g id="edge4" class="edge">
|
||||||
<title>PC:data--R1:data</title>
|
<title>PC:data--R1:data</title>
|
||||||
<path fill="none" stroke="black" stroke-width="2" d="M91.5,-155.01C91.5,-155.01 489.56,-155.01 489.56,-155.01"/>
|
<path fill="none" stroke="black" stroke-width="2" d="M91.5,-155.51C91.5,-155.51 497.56,-263.52 497.56,-263.52"/>
|
||||||
<text text-anchor="middle" x="430.56" y="-158.81" font-family="DejaVu Serif, Book" font-size="14.00">192.168.10.1/24</text>
|
<text text-anchor="middle" x="438.49" y="-270.35" font-family="DejaVu Serif, Book" font-size="14.00">192.168.10.1/24</text>
|
||||||
<text text-anchor="middle" x="150.5" y="-158.81" font-family="DejaVu Serif, Book" font-size="14.00">192.168.10.2/24</text>
|
<text text-anchor="middle" x="150.57" y="-141.29" font-family="DejaVu Serif, Book" font-size="14.00">192.168.10.2/24</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- R2 -->
|
<!-- R2 -->
|
||||||
<g id="node3" class="node">
|
<g id="node3" class="node">
|
||||||
<title>R2</title>
|
<title>R2</title>
|
||||||
<polygon fill="none" stroke="black" points="490.06,-0.5 490.06,-69.5 705.06,-69.5 705.06,-0.5 490.06,-0.5"/>
|
<polygon fill="none" stroke="black" points="498.06,-109.01 498.06,-178.01 713.06,-178.01 713.06,-109.01 498.06,-109.01"/>
|
||||||
<text text-anchor="middle" x="515.06" y="-54.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
<text text-anchor="middle" x="523.06" y="-162.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||||
<polyline fill="none" stroke="black" points="490.06,-46.5 540.06,-46.5 "/>
|
<polyline fill="none" stroke="black" points="498.06,-155.01 548.06,-155.01 "/>
|
||||||
<text text-anchor="middle" x="515.06" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
<text text-anchor="middle" x="523.06" y="-139.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||||
<polyline fill="none" stroke="black" points="490.06,-23.5 540.06,-23.5 "/>
|
<polyline fill="none" stroke="black" points="498.06,-132.01 548.06,-132.01 "/>
|
||||||
<text text-anchor="middle" x="515.06" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
<text text-anchor="middle" x="523.06" y="-116.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">data</text>
|
||||||
<polyline fill="none" stroke="black" points="540.06,-0.5 540.06,-69.5 "/>
|
<polyline fill="none" stroke="black" points="548.06,-109.01 548.06,-178.01 "/>
|
||||||
<text text-anchor="middle" x="622.56" y="-46.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2 </text>
|
<text text-anchor="middle" x="630.56" y="-154.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">R2 </text>
|
||||||
<text text-anchor="middle" x="622.56" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 192.168.200.1/32 </text>
|
<text text-anchor="middle" x="630.56" y="-139.81" font-family="DejaVu Sans Mono, Book" font-size="14.00"> 192.168.200.1/32 </text>
|
||||||
<text text-anchor="middle" x="622.56" y="-16.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
<text text-anchor="middle" x="630.56" y="-124.81" font-family="DejaVu Sans Mono, Book" font-size="14.00">(lo)</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- PC--R2 -->
|
<!-- PC--R2 -->
|
||||||
<g id="edge2" class="edge">
|
<g id="edge2" class="edge">
|
||||||
<title>PC:mgmt2--R2:mgmt</title>
|
<title>PC:mgmt2--R2:mgmt</title>
|
||||||
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-132.01C91.5,-132.01 489.56,-35 489.56,-35"/>
|
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-131.51C91.5,-131.51 497.56,-143.51 497.56,-143.51"/>
|
||||||
|
</g>
|
||||||
|
<!-- HOST -->
|
||||||
|
<g id="node4" class="node">
|
||||||
|
<title>HOST</title>
|
||||||
|
<polygon fill="none" stroke="black" points="499.05,-0.5 499.05,-46.5 656.05,-46.5 656.05,-0.5 499.05,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="524.05" y="-31.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">link</text>
|
||||||
|
<polyline fill="none" stroke="black" points="499.05,-23.5 549.05,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="524.05" y="-8.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
|
||||||
|
<polyline fill="none" stroke="black" points="549.05,-0.5 549.05,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="602.55" y="-27.3" font-family="DejaVu Sans Mono, Book" font-size="14.00">HOST </text>
|
||||||
|
<text text-anchor="middle" x="602.55" y="-12.3" font-family="DejaVu Sans Mono, Book" font-size="14.00"> end-device</text>
|
||||||
|
</g>
|
||||||
|
<!-- PC--HOST -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>PC:mgmt3--HOST:mgmt</title>
|
||||||
|
<path fill="none" stroke="lightgray" stroke-width="2" d="M91.5,-108.51C91.5,-108.51 498.55,-11.5 498.55,-11.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- R1--R2 -->
|
<!-- R1--R2 -->
|
||||||
<g id="edge4" class="edge">
|
<g id="edge5" class="edge">
|
||||||
<title>R1:link--R2:link</title>
|
<title>R1:link--R2:link</title>
|
||||||
<path fill="none" stroke="black" stroke-width="2" d="M514.56,-120.01C514.56,-120.01 514.56,-70 514.56,-70"/>
|
<path fill="none" stroke="black" stroke-width="2" d="M522.56,-228.52C522.56,-228.52 522.56,-178.51 522.56,-178.51"/>
|
||||||
<text text-anchor="middle" x="518.78" y="-75.36" font-family="DejaVu Serif, Book" font-size="14.00">192.168.50.2/24</text>
|
<text text-anchor="middle" x="526.78" y="-183.88" font-family="DejaVu Serif, Book" font-size="14.00">192.168.50.2/24</text>
|
||||||
<text text-anchor="middle" x="510.33" y="-107.25" font-family="DejaVu Serif, Book" font-size="14.00">192.168.50.1/24</text>
|
<text text-anchor="middle" x="518.33" y="-215.76" font-family="DejaVu Serif, Book" font-size="14.00">192.168.50.1/24</text>
|
||||||
|
</g>
|
||||||
|
<!-- R2--HOST -->
|
||||||
|
<g id="edge6" class="edge">
|
||||||
|
<title>R2:data--HOST:link</title>
|
||||||
|
<path fill="none" stroke="black" stroke-width="2" d="M522.56,-108.51C522.56,-108.51 523.55,-46.5 523.55,-46.5"/>
|
||||||
|
<text text-anchor="middle" x="527.63" y="-51.93" font-family="DejaVu Serif, Book" font-size="14.00">192.168.60.2/24</text>
|
||||||
|
<text text-anchor="middle" x="518.48" y="-95.68" font-family="DejaVu Serif, Book" font-size="14.00">192.168.60.1/24</text>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 6.5 KiB |
@@ -26,7 +26,6 @@ endif::topdoc[]
|
|||||||
. Set hostname to 'container-host'
|
. Set hostname to 'container-host'
|
||||||
. Create enabled container from bundled OCI image
|
. Create enabled container from bundled OCI image
|
||||||
. Verify container has started
|
. Verify container has started
|
||||||
. Let container settle
|
|
||||||
. Disable container
|
. Disable container
|
||||||
. Verify container has stopped
|
. Verify container has stopped
|
||||||
. Re-enable container
|
. Re-enable container
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
=== Container environment variables
|
=== Container environment variables
|
||||||
==== Description
|
==== Description
|
||||||
Verify that environment variables can be set in container configuration
|
Verify that environment variables can be set in container configuration
|
||||||
and are available inside the running container. Tests the 'env' list
|
and are available inside the running container.
|
||||||
functionality by:
|
|
||||||
|
|
||||||
1. Creating a container with multiple environment variables
|
1 Set up a container config with multiple environment variables
|
||||||
2. Using a custom script to extract env vars and serve them via HTTP
|
2. Serve variables back to host using a CGI script in container
|
||||||
3. Fetching the served content to verify environment variables are set correctly
|
3. Verify served content against environment variables
|
||||||
|
|
||||||
Uses the nftables container image with custom rc.local script.
|
|
||||||
|
|
||||||
==== Topology
|
==== Topology
|
||||||
ifdef::topdoc[]
|
ifdef::topdoc[]
|
||||||
@@ -25,11 +22,10 @@ endif::topdoc[]
|
|||||||
==== Test sequence
|
==== Test sequence
|
||||||
. Set up topology and attach to target DUT
|
. Set up topology and attach to target DUT
|
||||||
. Configure data interface with static IPv4
|
. Configure data interface with static IPv4
|
||||||
. Create container with environment variables
|
. Set up container with environment variables
|
||||||
. Verify container has started
|
. Verify container has started
|
||||||
. Verify environment variables are available via HTTP
|
|
||||||
. Verify basic connectivity to data interface
|
. Verify basic connectivity to data interface
|
||||||
. Verify environment variables in HTTP response
|
. Verify environment variables in CGI response
|
||||||
|
|
||||||
|
|
||||||
<<<
|
<<<
|
||||||
|
|||||||
+55
-9
@@ -1,26 +1,72 @@
|
|||||||
"""Fugly URL fetcher"""
|
"""Simple HTTP URL fetcher and content checker
|
||||||
|
|
||||||
|
This module provides the a lightweight wrapper around urllib for testing
|
||||||
|
HTTP endpoints. It's designed specifically for test scenarios where you
|
||||||
|
need to:
|
||||||
|
|
||||||
|
- Fetch HTTP content and verify it contains expected strings
|
||||||
|
- Perform checks from within network namespaces
|
||||||
|
- Validate multiple content patterns in a single request
|
||||||
|
- Handle network errors gracefully in test environments
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
# Single needle check
|
||||||
|
url = Furl("http://example.com/api")
|
||||||
|
if url.check("success"):
|
||||||
|
print("API returned success")
|
||||||
|
|
||||||
|
# Multiple needle check (all must match)
|
||||||
|
if url.check(["user: alice", "status: active", "role: admin"]):
|
||||||
|
print("All user details found")
|
||||||
|
|
||||||
|
# Check from network namespace
|
||||||
|
with IsolatedMacVlan("eth0") as ns:
|
||||||
|
if url.nscheck(ns, "expected content"):
|
||||||
|
print("Content verified from namespace")
|
||||||
|
"""
|
||||||
|
|
||||||
import urllib.error
|
import urllib.error
|
||||||
|
import urllib.parse
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
|
||||||
|
|
||||||
class Furl:
|
class Furl:
|
||||||
"""Furl wraps urllib in a way similar to curl"""
|
"""Furl wraps urllib in a way similar to curl"""
|
||||||
def __init__(self, url):
|
def __init__(self, url):
|
||||||
"""Create new URL checker"""
|
"""Create new URL checker"""
|
||||||
self.url = urllib.parse.quote(url, safe='/:')
|
self.url = urllib.parse.quote(url, safe='/:')
|
||||||
|
|
||||||
def check(self, needle, timeout=10):
|
def check(self, needles, timeout=10):
|
||||||
"""Connect to web server URL, fetch body and check for needle"""
|
"""Connect to web server URL, fetch body and check for needle(s)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
needles: String or list of strings to search for in response
|
||||||
|
timeout: Request timeout in seconds
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if all needles found in response, False otherwise
|
||||||
|
"""
|
||||||
|
# Backwards compat, make needles a list for uniform processing
|
||||||
|
if isinstance(needles, str):
|
||||||
|
needles = [needles]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with urllib.request.urlopen(self.url, timeout=timeout) as response:
|
with urllib.request.urlopen(self.url, timeout=timeout) as response:
|
||||||
text = response.read().decode('utf-8')
|
text = response.read().decode('utf-8')
|
||||||
#print(text)
|
return all(needle in text for needle in needles)
|
||||||
return needle in text
|
except urllib.error.URLError:
|
||||||
except urllib.error.URLError as _:
|
|
||||||
return False
|
return False
|
||||||
except ConnectionResetError:
|
except ConnectionResetError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def nscheck(self, netns, needle):
|
def nscheck(self, netns, needles):
|
||||||
""""Call check() from netns"""
|
""""Call check() from netns
|
||||||
return netns.call(lambda: self.check(needle))
|
|
||||||
|
Args:
|
||||||
|
netns: Network namespace to call from
|
||||||
|
needles: String or list of strings to search for in response
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if all needles found in response, False otherwise
|
||||||
|
"""
|
||||||
|
return netns.call(lambda: self.check(needles))
|
||||||
|
|||||||
@@ -150,7 +150,6 @@ class Device(Transport):
|
|||||||
url = f"{self.yang_url}/{schema_name}"
|
url = f"{self.yang_url}/{schema_name}"
|
||||||
data = self._get_raw(url=url, parse=False)
|
data = self._get_raw(url=url, parse=False)
|
||||||
|
|
||||||
sys.stdout.write(f"Downloading YANG model {schema_name} ...\r\033[K")
|
|
||||||
data = data.decode('utf-8')
|
data = data.decode('utf-8')
|
||||||
with open(f"{yangdir}/{schema_name}", 'w') as json_file:
|
with open(f"{yangdir}/{schema_name}", 'w') as json_file:
|
||||||
json_file.write(data)
|
json_file.write(data)
|
||||||
|
|||||||
@@ -114,3 +114,13 @@ def ospf_is_area_nssa(target, area_id):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def ospf_has_neighbors(target):
|
||||||
|
ospf = _get_ospf_status(target)
|
||||||
|
for area in ospf.get("areas", {}).get("area", []):
|
||||||
|
for interface in area.get("interfaces", {}).get("interface", []):
|
||||||
|
if interface.get("neighbors"):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|||||||
+15
-5
@@ -1,9 +1,10 @@
|
|||||||
base-dir := $(lastword $(subst :, ,$(BR2_EXTERNAL)))
|
base-dir := $(lastword $(subst :, ,$(BR2_EXTERNAL)))
|
||||||
test-dir := $(BR2_EXTERNAL_INFIX_PATH)/test
|
test-dir ?= $(BR2_EXTERNAL_INFIX_PATH)/test
|
||||||
ninepm := $(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py
|
ninepm := $(BR2_EXTERNAL_INFIX_PATH)/test/9pm/9pm.py
|
||||||
|
NINEPM_PROJ_CONF ?= $(BR2_EXTERNAL_INFIX_PATH)/test/9pm-proj.yaml
|
||||||
spec-dir := $(test-dir)/spec
|
spec-dir := $(test-dir)/spec
|
||||||
test-specification := $(O)/images/test-specification.pdf
|
test-specification := $(BINARIES_DIR)/test-specification.pdf
|
||||||
|
test-report := $(BINARIES_DIR)/test-report.pdf
|
||||||
UNIT_TESTS ?= $(test-dir)/case/all-repo.yaml $(test-dir)/case/all-unit.yaml
|
UNIT_TESTS ?= $(test-dir)/case/all-repo.yaml $(test-dir)/case/all-unit.yaml
|
||||||
TESTS ?= $(test-dir)/case/all.yaml
|
TESTS ?= $(test-dir)/case/all.yaml
|
||||||
|
|
||||||
@@ -33,9 +34,18 @@ test-sh:
|
|||||||
|
|
||||||
test-spec:
|
test-spec:
|
||||||
@esc_infix_name="$(echo $(INFIX_NAME) | sed 's/\//\\\//g')"; \
|
@esc_infix_name="$(echo $(INFIX_NAME) | sed 's/\//\\\//g')"; \
|
||||||
sed 's/{REPLACE}/$(subst ",,$(esc_infix_name)) $(INFIX_VERSION)/' $(spec-dir)/Readme.adoc.in > $(spec-dir)/Readme.adoc
|
sed 's/{REPLACE}/$(subst ",,$(esc_infix_name)) $(INFIX_VERSION)/' \
|
||||||
|
$(spec-dir)/Readme.adoc.in > $(spec-dir)/Readme.adoc
|
||||||
@$(spec-dir)/generate_spec.py -s $(test-dir)/case/all.yaml -r $(BR2_EXTERNAL_INFIX_PATH)
|
@$(spec-dir)/generate_spec.py -s $(test-dir)/case/all.yaml -r $(BR2_EXTERNAL_INFIX_PATH)
|
||||||
@asciidoctor-pdf --failure-level INFO --theme $(spec-dir)/theme.yml -a pdf-fontsdir=$(spec-dir)/fonts -o $(test-specification) $(spec-dir)/Readme.adoc
|
@asciidoctor-pdf --failure-level INFO --theme $(spec-dir)/theme.yml \
|
||||||
|
-a pdf-fontsdir=$(spec-dir)/fonts \
|
||||||
|
-o $(test-specification) $(spec-dir)/Readme.adoc
|
||||||
|
|
||||||
|
test-report:
|
||||||
|
asciidoctor-pdf --theme $(spec-dir)/theme.yml \
|
||||||
|
-a logo="image:$(LOGO)" \
|
||||||
|
-a pdf-fontsdir=$(spec-dir)/fonts \
|
||||||
|
-o $(test-report) $(test-dir)/.log/last/report.adoc
|
||||||
|
|
||||||
# Unit tests run with random (-r) hostname and container name to
|
# Unit tests run with random (-r) hostname and container name to
|
||||||
# prevent race conditions when running in CI environments.
|
# prevent race conditions when running in CI environments.
|
||||||
|
|||||||
Reference in New Issue
Block a user