This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
*.patch -whitespace
|
||||||
@@ -27,6 +27,6 @@ jobs:
|
|||||||
- name: Validate metadata, patches, and process manager
|
- name: Validate metadata, patches, and process manager
|
||||||
run: pytest -q
|
run: pytest -q
|
||||||
- name: Build amd64 image
|
- name: Build amd64 image
|
||||||
run: docker build --build-arg BUILD_ARCH=amd64 --tag homeassistant-stelloauth-addon:test stelloauth
|
run: docker buildx build --platform linux/amd64 --build-arg BUILD_ARCH=amd64 --load --tag homeassistant-stelloauth-addon:test stelloauth
|
||||||
- name: Exercise runtime
|
- name: Exercise runtime
|
||||||
run: SKIP_BUILD=1 tests/test_runtime.sh
|
run: SKIP_BUILD=1 tests/test_runtime.sh
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@
|
|||||||
9. De målte resultater fra den reelle `linux/amd64`-kørsel under Rosetta var:
|
9. De målte resultater fra den reelle `linux/amd64`-kørsel under Rosetta var:
|
||||||
|
|
||||||
- Image: 2,571,693,650 bytes (2.571 GB decimal / 2452.56 MiB).
|
- Image: 2,571,693,650 bytes (2.571 GB decimal / 2452.56 MiB).
|
||||||
- Seneste idle RAM: 121.5 MiB.
|
- Dokumenteret Task 4-måling: 121,5 MiB.
|
||||||
- Stop: cirka 9.3 sekunder.
|
- Stop: cirka 9.3 sekunder.
|
||||||
- `amd64` runtime bestod under Rosetta; `aarch64` build bestod.
|
- `amd64` runtime bestod under Rosetta; `aarch64` build bestod.
|
||||||
- Mål-HAOS havde ved inspektionen approximately 4 GB free. Den knappe
|
- Mål-HAOS havde ved inspektionen approximately 4 GB free. Den knappe
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ ARG BUILD_VERSION="0.1.0"
|
|||||||
LABEL io.hass.name="$BUILD_NAME" \
|
LABEL io.hass.name="$BUILD_NAME" \
|
||||||
io.hass.description="$BUILD_DESCRIPTION" \
|
io.hass.description="$BUILD_DESCRIPTION" \
|
||||||
io.hass.arch="$BUILD_ARCH" \
|
io.hass.arch="$BUILD_ARCH" \
|
||||||
io.hass.type="addon" \
|
io.hass.type="app" \
|
||||||
io.hass.version="$BUILD_VERSION" \
|
io.hass.version="$BUILD_VERSION" \
|
||||||
org.opencontainers.image.created="$BUILD_DATE" \
|
org.opencontainers.image.created="$BUILD_DATE" \
|
||||||
org.opencontainers.image.revision="$BUILD_REF" \
|
org.opencontainers.image.revision="$BUILD_REF" \
|
||||||
|
|||||||
@@ -157,10 +157,10 @@ index 48a487e..946d8cf 100644
|
|||||||
flusher.Flush()
|
flusher.Flush()
|
||||||
return
|
return
|
||||||
diff --git a/internal/app/server_test.go b/internal/app/server_test.go
|
diff --git a/internal/app/server_test.go b/internal/app/server_test.go
|
||||||
index b56bb27..c9ab68e 100644
|
index b56bb27..730e658 100644
|
||||||
--- a/internal/app/server_test.go
|
--- a/internal/app/server_test.go
|
||||||
+++ b/internal/app/server_test.go
|
+++ b/internal/app/server_test.go
|
||||||
@@ -1,7 +1,10 @@
|
@@ -1,12 +1,16 @@
|
||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -171,7 +171,61 @@ index b56bb27..c9ab68e 100644
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
@@ -188,3 +191,74 @@ func TestParseClientIP(t *testing.T) {
|
"strings"
|
||||||
|
"testing"
|
||||||
|
+ "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
@@ -101,6 +105,47 @@ func TestHandleOAuth_InvalidBody(t *testing.T) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+func useSingleRequestRateLimiter(t *testing.T) {
|
||||||
|
+ t.Helper()
|
||||||
|
+ previous := rateLimiter
|
||||||
|
+ rateLimiter = &RateLimiter{
|
||||||
|
+ requests: make(map[string][]time.Time),
|
||||||
|
+ refunds: make(map[string][]time.Time),
|
||||||
|
+ limit: 1,
|
||||||
|
+ window: time.Hour,
|
||||||
|
+ enabled: true,
|
||||||
|
+ }
|
||||||
|
+ t.Cleanup(func() { rateLimiter = previous })
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func setSpoofedClientHeaders(req *http.Request, suffix string) {
|
||||||
|
+ req.Header.Set("Forwarded", "for=203.0.113."+suffix)
|
||||||
|
+ req.Header.Set("X-Forwarded-For", "198.51.100."+suffix)
|
||||||
|
+ req.Header.Set("X-Real-IP", "192.0.2."+suffix)
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+func TestHandleOAuthRateLimitUsesDirectPeer(t *testing.T) {
|
||||||
|
+ useSingleRequestRateLimiter(t)
|
||||||
|
+
|
||||||
|
+ first := httptest.NewRequest(http.MethodPost, "/oauth", strings.NewReader("invalid json"))
|
||||||
|
+ first.RemoteAddr = "10.0.0.8:41001"
|
||||||
|
+ setSpoofedClientHeaders(first, "11")
|
||||||
|
+ firstResponse := httptest.NewRecorder()
|
||||||
|
+ handleOAuth(firstResponse, first)
|
||||||
|
+ if firstResponse.Code != http.StatusBadRequest {
|
||||||
|
+ t.Fatalf("first status = %d, want %d", firstResponse.Code, http.StatusBadRequest)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ second := httptest.NewRequest(http.MethodPost, "/oauth", strings.NewReader("invalid json"))
|
||||||
|
+ second.RemoteAddr = "10.0.0.8:41001"
|
||||||
|
+ setSpoofedClientHeaders(second, "22")
|
||||||
|
+ secondResponse := httptest.NewRecorder()
|
||||||
|
+ handleOAuth(secondResponse, second)
|
||||||
|
+ if secondResponse.Code != http.StatusTooManyRequests {
|
||||||
|
+ t.Fatalf("second status = %d, want %d", secondResponse.Code, http.StatusTooManyRequests)
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
func TestHandleOAuth_MissingFields(t *testing.T) {
|
||||||
|
body := `{"brand":"MyPeugeot","country":"","email":"","password":""}`
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/oauth", strings.NewReader(body))
|
||||||
|
@@ -188,3 +233,74 @@ func TestParseClientIP(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,7 +408,7 @@ index 00b9cf8..3dbe54a 100644
|
|||||||
// authorize URL's redirect_uri query parameter; the code-capture listener keys on
|
// authorize URL's redirect_uri query parameter; the code-capture listener keys on
|
||||||
// "<scheme>://".
|
// "<scheme>://".
|
||||||
diff --git a/internal/app/worker_test.go b/internal/app/worker_test.go
|
diff --git a/internal/app/worker_test.go b/internal/app/worker_test.go
|
||||||
index e64964d..2a05a3b 100644
|
index e64964d..7141640 100644
|
||||||
--- a/internal/app/worker_test.go
|
--- a/internal/app/worker_test.go
|
||||||
+++ b/internal/app/worker_test.go
|
+++ b/internal/app/worker_test.go
|
||||||
@@ -2,12 +2,81 @@ package app
|
@@ -2,12 +2,81 @@ package app
|
||||||
@@ -439,10 +493,32 @@ index e64964d..2a05a3b 100644
|
|||||||
func TestHandleWorker_MethodNotAllowed(t *testing.T) {
|
func TestHandleWorker_MethodNotAllowed(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodGet, "/worker", nil)
|
req := httptest.NewRequest(http.MethodGet, "/worker", nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
@@ -30,6 +99,25 @@ func TestHandleWorker_InvalidBody(t *testing.T) {
|
@@ -30,6 +99,47 @@ func TestHandleWorker_InvalidBody(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+func TestHandleWorkerRateLimitUsesDirectPeer(t *testing.T) {
|
||||||
|
+ useSingleRequestRateLimiter(t)
|
||||||
|
+
|
||||||
|
+ first := httptest.NewRequest(http.MethodPost, "/worker", strings.NewReader("invalid json"))
|
||||||
|
+ first.RemoteAddr = "10.0.0.9:41002"
|
||||||
|
+ setSpoofedClientHeaders(first, "33")
|
||||||
|
+ firstResponse := httptest.NewRecorder()
|
||||||
|
+ handleWorker(firstResponse, first)
|
||||||
|
+ if firstResponse.Code != http.StatusBadRequest {
|
||||||
|
+ t.Fatalf("first status = %d, want %d", firstResponse.Code, http.StatusBadRequest)
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ second := httptest.NewRequest(http.MethodPost, "/worker", strings.NewReader("invalid json"))
|
||||||
|
+ second.RemoteAddr = "10.0.0.9:41002"
|
||||||
|
+ setSpoofedClientHeaders(second, "44")
|
||||||
|
+ secondResponse := httptest.NewRecorder()
|
||||||
|
+ handleWorker(secondResponse, second)
|
||||||
|
+ if secondResponse.Code != http.StatusTooManyRequests {
|
||||||
|
+ t.Fatalf("second status = %d, want %d", secondResponse.Code, http.StatusTooManyRequests)
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
+func TestHandleWorker_RequestTooLarge(t *testing.T) {
|
+func TestHandleWorker_RequestTooLarge(t *testing.T) {
|
||||||
+ body := `{"url":"` + strings.Repeat("x", 65<<10) + `"}`
|
+ body := `{"url":"` + strings.Repeat("x", 65<<10) + `"}`
|
||||||
+ req := httptest.NewRequest(http.MethodPost, "/worker", strings.NewReader(body))
|
+ req := httptest.NewRequest(http.MethodPost, "/worker", strings.NewReader(body))
|
||||||
@@ -465,7 +541,7 @@ index e64964d..2a05a3b 100644
|
|||||||
func TestHandleWorker_MissingParams(t *testing.T) {
|
func TestHandleWorker_MissingParams(t *testing.T) {
|
||||||
body := `{"url":"","email":"","password":""}`
|
body := `{"url":"","email":"","password":""}`
|
||||||
req := httptest.NewRequest(http.MethodPost, "/worker", strings.NewReader(body))
|
req := httptest.NewRequest(http.MethodPost, "/worker", strings.NewReader(body))
|
||||||
@@ -83,7 +171,7 @@ func TestRedirectScheme(t *testing.T) {
|
@@ -83,7 +193,7 @@ func TestRedirectScheme(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "opel custom scheme",
|
name: "opel custom scheme",
|
||||||
|
|||||||
@@ -51,26 +51,40 @@ def test_repository_hostname_derivation() -> None:
|
|||||||
assert f"{repository_id}-stelloauth" == "0031621f-stelloauth"
|
assert f"{repository_id}-stelloauth" == "0031621f-stelloauth"
|
||||||
|
|
||||||
|
|
||||||
def test_documentation_contract() -> None:
|
def test_user_guide_documentation_contract() -> None:
|
||||||
documentation = "\n".join(
|
documentation = (ROOT / "stelloauth/DOCS.md").read_text(encoding="utf-8")
|
||||||
(ROOT / path).read_text(encoding="utf-8")
|
|
||||||
for path in ("README.md", "stelloauth/README.md", "stelloauth/DOCS.md")
|
|
||||||
)
|
|
||||||
for required_text in (
|
for required_text in (
|
||||||
REPOSITORY_URL,
|
REPOSITORY_URL,
|
||||||
|
"Installér **Stelloauth**",
|
||||||
|
"aktivér **Start ved opstart** og **Watchdog**",
|
||||||
"http://0031621f-stelloauth:8080/worker",
|
"http://0031621f-stelloauth:8080/worker",
|
||||||
"http://192.168.1.20:8080/worker",
|
"http://192.168.1.20:8080/worker",
|
||||||
"Brand: Opel",
|
"Brand: Opel",
|
||||||
"Country: DK",
|
"Country: DK",
|
||||||
"v0.6.0",
|
"Image: 2,571,693,650 bytes (2.571 GB decimal / 2452.56 MiB).",
|
||||||
"0.5.10",
|
"Dokumenteret Task 4-måling: 121,5 MiB.",
|
||||||
"CloakBrowser Binary License",
|
"Stop: cirka 9.3 sekunder.",
|
||||||
"approximately 4 GB free",
|
"approximately 4 GB free",
|
||||||
"Der er ikke gennemført et live MyOpel-login.",
|
"Der er ikke gennemført et live MyOpel-login.",
|
||||||
"Login-flow RAM: not measured without real MyOpel credentials.",
|
"Login-flow RAM: not measured without real MyOpel credentials.",
|
||||||
):
|
):
|
||||||
assert required_text in documentation
|
assert required_text in documentation
|
||||||
assert "deaktivér porttilknytningen igen" in documentation
|
assert "deaktivér porttilknytningen igen" in documentation
|
||||||
|
assert "Seneste idle RAM" not in documentation
|
||||||
|
|
||||||
|
|
||||||
|
def test_root_readme_repository_source_and_license_facts() -> None:
|
||||||
|
readme = (ROOT / "README.md").read_text(encoding="utf-8")
|
||||||
|
for required_text in (
|
||||||
|
REPOSITORY_URL,
|
||||||
|
"v0.6.0",
|
||||||
|
"367d4f8c02a3b072c59142c49dffc129edc8548b",
|
||||||
|
"0.5.10",
|
||||||
|
"f04c23da285b3b3d3cf10c8f9d282e7adc1d52ce",
|
||||||
|
"CloakBrowser Binary License",
|
||||||
|
"MIT-licenseret",
|
||||||
|
):
|
||||||
|
assert required_text in readme
|
||||||
|
|
||||||
def test_translations_cover_every_option() -> None:
|
def test_translations_cover_every_option() -> None:
|
||||||
keys = set(load_yaml("stelloauth/config.yaml")["options"])
|
keys = set(load_yaml("stelloauth/config.yaml")["options"])
|
||||||
@@ -107,6 +121,8 @@ def test_dockerfile_declares_home_assistant_runtime_contract() -> None:
|
|||||||
"io.hass.version",
|
"io.hass.version",
|
||||||
):
|
):
|
||||||
assert label in dockerfile
|
assert label in dockerfile
|
||||||
|
assert 'io.hass.type="app"' in dockerfile
|
||||||
|
assert 'io.hass.type="addon"' not in dockerfile
|
||||||
assert re.search(r"^EXPOSE 8080$", dockerfile, re.MULTILINE)
|
assert re.search(r"^EXPOSE 8080$", dockerfile, re.MULTILINE)
|
||||||
assert not re.search(r"^EXPOSE .*\b9222\b", dockerfile, re.MULTILINE)
|
assert not re.search(r"^EXPOSE .*\b9222\b", dockerfile, re.MULTILINE)
|
||||||
assert "ENTRYPOINT []" in dockerfile
|
assert "ENTRYPOINT []" in dockerfile
|
||||||
@@ -127,6 +143,64 @@ def test_runtime_accepts_docker_port_unpublished_status() -> None:
|
|||||||
assert 'docker port "$container" 9222/tcp 2>/dev/null || true' in runtime_test
|
assert 'docker port "$container" 9222/tcp 2>/dev/null || true' in runtime_test
|
||||||
|
|
||||||
|
|
||||||
|
def test_ci_builds_and_loads_only_the_amd64_test_image() -> None:
|
||||||
|
workflow = (ROOT / ".gitea/workflows/ci.yml").read_text(encoding="utf-8")
|
||||||
|
parsed = yaml.safe_load(workflow)
|
||||||
|
steps = parsed["jobs"]["validate"]["steps"]
|
||||||
|
build_command = next(
|
||||||
|
step["run"] for step in steps if step.get("name") == "Build amd64 image"
|
||||||
|
)
|
||||||
|
assert build_command.split() == [
|
||||||
|
"docker",
|
||||||
|
"buildx",
|
||||||
|
"build",
|
||||||
|
"--platform",
|
||||||
|
"linux/amd64",
|
||||||
|
"--build-arg",
|
||||||
|
"BUILD_ARCH=amd64",
|
||||||
|
"--load",
|
||||||
|
"--tag",
|
||||||
|
"homeassistant-stelloauth-addon:test",
|
||||||
|
"stelloauth",
|
||||||
|
]
|
||||||
|
for publication_primitive in (
|
||||||
|
"--push",
|
||||||
|
"docker push",
|
||||||
|
"docker/login-action",
|
||||||
|
"docker/build-push-action",
|
||||||
|
"packages: write",
|
||||||
|
):
|
||||||
|
assert publication_primitive not in workflow
|
||||||
|
|
||||||
|
|
||||||
|
def test_patch_payloads_disable_git_whitespace_errors() -> None:
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
"git",
|
||||||
|
"check-attr",
|
||||||
|
"whitespace",
|
||||||
|
"--",
|
||||||
|
"stelloauth/patches/stelloauth-security.patch",
|
||||||
|
"stelloauth/patches/cloakserve-loopback.patch",
|
||||||
|
],
|
||||||
|
cwd=ROOT,
|
||||||
|
text=True,
|
||||||
|
capture_output=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
assert result.stdout.splitlines() == [
|
||||||
|
"stelloauth/patches/stelloauth-security.patch: whitespace: unset",
|
||||||
|
"stelloauth/patches/cloakserve-loopback.patch: whitespace: unset",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_runtime_rejects_every_ipv6_cdp_listener() -> None:
|
||||||
|
runtime_test = (ROOT / "tests/test_runtime.sh").read_text(encoding="utf-8")
|
||||||
|
assert 'cat /proc/net/tcp6 > "$tcp6_artifact"' in runtime_test
|
||||||
|
assert 'for table in ("/proc/net/tcp", "/proc/net/tcp6"):' in runtime_test
|
||||||
|
assert 'if table == "/proc/net/tcp6":' in runtime_test
|
||||||
|
|
||||||
|
|
||||||
def test_runtime_requires_process_baseline_after_cdp_close_and_zero_stopped_pid() -> None:
|
def test_runtime_requires_process_baseline_after_cdp_close_and_zero_stopped_pid() -> None:
|
||||||
runtime_test = (ROOT / "tests/test_runtime.sh").read_text(encoding="utf-8")
|
runtime_test = (ROOT / "tests/test_runtime.sh").read_text(encoding="utf-8")
|
||||||
assert 'docker top "$container" -eo pid,args' in runtime_test
|
assert 'docker top "$container" -eo pid,args' in runtime_test
|
||||||
|
|||||||
+30
-16
@@ -209,26 +209,34 @@ assert_processes_return_to_baseline() {
|
|||||||
|
|
||||||
assert_loopback_cdp_listener() {
|
assert_loopback_cdp_listener() {
|
||||||
local container="$1"
|
local container="$1"
|
||||||
local artifact="$2"
|
local tcp_artifact="$2"
|
||||||
docker exec "$container" cat /proc/net/tcp > "$artifact"
|
local tcp6_artifact="$3"
|
||||||
|
docker exec "$container" cat /proc/net/tcp > "$tcp_artifact"
|
||||||
|
docker exec "$container" cat /proc/net/tcp6 > "$tcp6_artifact"
|
||||||
docker exec -i "$container" python3 - <<'PY'
|
docker exec -i "$container" python3 - <<'PY'
|
||||||
expected = f"0100007F:{9222:04X}"
|
expected = f"0100007F:{9222:04X}"
|
||||||
wildcard = f"00000000:{9222:04X}"
|
|
||||||
if expected != "0100007F:2406":
|
if expected != "0100007F:2406":
|
||||||
raise SystemExit(f"unexpected 9222 hexadecimal encoding: {expected}")
|
raise SystemExit(f"unexpected 9222 hexadecimal encoding: {expected}")
|
||||||
|
|
||||||
listeners = set()
|
listeners = {"/proc/net/tcp": set(), "/proc/net/tcp6": set()}
|
||||||
with open("/proc/net/tcp", encoding="ascii") as handle:
|
for table in ("/proc/net/tcp", "/proc/net/tcp6"):
|
||||||
next(handle)
|
with open(table, encoding="ascii") as handle:
|
||||||
for line in handle:
|
next(handle)
|
||||||
fields = line.split()
|
for line in handle:
|
||||||
if len(fields) >= 4 and fields[3] == "0A":
|
fields = line.split()
|
||||||
listeners.add(fields[1].upper())
|
if len(fields) < 4 or fields[3] != "0A":
|
||||||
|
continue
|
||||||
|
local_address = fields[1].upper()
|
||||||
|
if local_address.rsplit(":", 1)[-1] != "2406":
|
||||||
|
continue
|
||||||
|
listeners[table].add(local_address)
|
||||||
|
if table == "/proc/net/tcp6":
|
||||||
|
raise SystemExit(f"IPv6 CDP listener present: {local_address}")
|
||||||
|
|
||||||
if expected not in listeners:
|
if listeners["/proc/net/tcp"] != {expected}:
|
||||||
raise SystemExit(f"missing loopback CDP listener {expected}: {sorted(listeners)}")
|
raise SystemExit(
|
||||||
if wildcard in listeners:
|
f"IPv4 CDP listeners = {sorted(listeners['/proc/net/tcp'])}, want [{expected}]"
|
||||||
raise SystemExit(f"wildcard CDP listener present: {wildcard}")
|
)
|
||||||
PY
|
PY
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +378,10 @@ first_port="$(host_port "$first_container")"
|
|||||||
wait_ready "$first_container" "$first_port"
|
wait_ready "$first_container" "$first_port"
|
||||||
first_baseline="$(capture_process_baseline "$first_container")"
|
first_baseline="$(capture_process_baseline "$first_container")"
|
||||||
assert_no_9222_mapping "$first_container"
|
assert_no_9222_mapping "$first_container"
|
||||||
assert_loopback_cdp_listener "$first_container" "${artifacts_dir}/runtime-proc-net-tcp.txt"
|
assert_loopback_cdp_listener \
|
||||||
|
"$first_container" \
|
||||||
|
"${artifacts_dir}/runtime-proc-net-tcp.txt" \
|
||||||
|
"${artifacts_dir}/runtime-proc-net-tcp6.txt"
|
||||||
probe_and_close_cdp "$first_container"
|
probe_and_close_cdp "$first_container"
|
||||||
assert_processes_return_to_baseline "$first_container" "$first_baseline"
|
assert_processes_return_to_baseline "$first_container" "$first_baseline"
|
||||||
post_invalid_worker "$first_port" "${artifacts_dir}/runtime-invalid-worker-response.json"
|
post_invalid_worker "$first_port" "${artifacts_dir}/runtime-invalid-worker-response.json"
|
||||||
@@ -383,7 +394,10 @@ second_port="$(host_port "$second_container")"
|
|||||||
wait_ready "$second_container" "$second_port"
|
wait_ready "$second_container" "$second_port"
|
||||||
second_baseline="$(capture_process_baseline "$second_container")"
|
second_baseline="$(capture_process_baseline "$second_container")"
|
||||||
assert_no_9222_mapping "$second_container"
|
assert_no_9222_mapping "$second_container"
|
||||||
assert_loopback_cdp_listener "$second_container" "${artifacts_dir}/runtime-restart-proc-net-tcp.txt"
|
assert_loopback_cdp_listener \
|
||||||
|
"$second_container" \
|
||||||
|
"${artifacts_dir}/runtime-restart-proc-net-tcp.txt" \
|
||||||
|
"${artifacts_dir}/runtime-restart-proc-net-tcp6.txt"
|
||||||
probe_and_close_cdp "$second_container"
|
probe_and_close_cdp "$second_container"
|
||||||
assert_processes_return_to_baseline "$second_container" "$second_baseline"
|
assert_processes_return_to_baseline "$second_container" "$second_baseline"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user