v0.34.0_1
This commit is contained in:
1 parent
9b3d6731cc
commit
00f29f92c8
68 files changed
+2599
-513
No files matched your search
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
"""0.34.0 source-wiring checks only; do not mistake these for Rust tests."""
|
||||
from pathlib import Path
|
||||
import tomllib
|
||||
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
read = lambda path: (root / path).read_text()
|
||||
assert tomllib.loads(read("Cargo.toml"))["package"]["version"] == "0.34.0"
|
||||
assert 'version = "0.34.0"' in read("Cargo.lock")
|
||||
app = read("src/runtime/updates.rs")
|
||||
assert "CacheInvalidation::Scopes(scopes)" in app
|
||||
assert "this.cache.purge_scope(&scope)" in app
|
||||
assert "this.cache.set_control_revision(envelope.revision)" in app
|
||||
assert app.index("this.cache.set_control_revision(envelope.revision)") < app.index("match invalidation")
|
||||
source = read("src/runtime/types.rs")
|
||||
assert "view.load_balancing = Default::default();" in source
|
||||
assert "member.max_concurrent_requests = 0;" in source
|
||||
assert "fn vhost_cache_revision" in source
|
||||
assert "&web_services" in source
|
||||
assert "service.sendfile = crate::web_server::SendfileMode::Off;" in source
|
||||
assert "&config.php_fpm_profiles" in source
|
||||
for filename in ("src/proxy/forward/route_cache.rs", "src/proxy/forward/web_source.rs"):
|
||||
assert "ticket_scoped_for_config(" in read(filename)
|
||||
assert "snapshot.envelope.revision" in read(filename)
|
||||
assert "expected_control_revision" in read("src/cache/tickets.rs")
|
||||
assert "file.scope_revision != expected_scope_revision" in read("src/cache/cold/startup.rs")
|
||||
assert "scope_revision: draft.scope_revision" in read("src/cache/cold/worker.rs")
|
||||
body = read("src/proxy/body.rs")
|
||||
assert "response_backend: Option<Arc<crate::balance::Lease>>" in body
|
||||
assert "lease.bytes(count, false);" in body
|
||||
assert "exchange.backend_bytes(count, true)" in body
|
||||
assert "cold_scope_fingerprint_preserves_unmodified_vhost" in read("src/cache/tests/cold_tier_tests.rs")
|
||||
assert "stale_snapshot_cannot_issue_cache_ticket" in read("src/cache/tests/scope_tests.rs")
|
||||
for file in (root / 'src').rglob('*.rs'):
|
||||
if '/tests/' in file.as_posix() or file.name == 'tests.rs':
|
||||
continue
|
||||
if len(file.read_text().splitlines()) > 500:
|
||||
raise AssertionError(f"production Rust source exceeds 500 lines: {file}")
|
||||
print('PASS source wiring for scoped invalidation, cold fingerprints, stale-snapshot barrier, response accounting and <=500-line modules (STATIC ONLY)')
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Source-only guardrails for the uncompiled 0.34.0 hot-path candidate."""
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
def src(path):
|
||||
return (ROOT / path).read_text()
|
||||
|
||||
snapshot = src("src/config/snapshot.rs")
|
||||
assert "fn host_patterns(host: &str) -> impl Iterator" in snapshot
|
||||
assert "pub fn select_on_arc(" in snapshot
|
||||
assert "self.select_on_arc(host, path, local, tls).map(Arc::as_ref)" in snapshot
|
||||
assert "Vec<Arc<CompiledRoute>>" in src("src/config/model.rs")
|
||||
assert "route: Option<Arc<crate::config::CompiledRoute>>" in src("src/proxy/types.rs")
|
||||
assert "request.extensions_mut().insert(SelectedRouteContext" in src("src/proxy/upstream_helpers.rs")
|
||||
assert "selection.route.as_deref()" in src("src/proxy/forward_entry.rs")
|
||||
assert "let fallback_request = selected" in src("src/proxy/forward_entry.rs")
|
||||
assert "filter(|route| route.error_fallback.is_some())" in src("src/proxy/forward_entry.rs")
|
||||
assert "let Some(next_request) = replay_headers" in src("src/proxy/forward/upstream.rs") or "replay_headers.as_ref().and_then" in src("src/proxy/forward/upstream.rs")
|
||||
assert "let replay_headers = ((pool_retry_possible || h2_replay_possible)" in src("src/proxy/forward/upstream.rs")
|
||||
pool = src("src/balance/pool_core.rs")
|
||||
assert "if self.members.len() == 1 && !self.cookie_affinity()" in pool
|
||||
assert "let mut scheduling = lock(&self.scheduling);" in pool
|
||||
assert "fn candidates_excluding" in pool
|
||||
assert "health: member.health_settings.clone()" in pool
|
||||
assert "health: selected.health_settings.clone()" in pool
|
||||
assert "health_settings: Arc<HealthCheck>" in src("src/balance/health.rs")
|
||||
assert "healthy_cached: AtomicBool" in src("src/balance/model.rs")
|
||||
assert "self.healthy_cached.store(h.healthy, Ordering::Release)" in src("src/balance/health.rs")
|
||||
exchange = src("src/proxy/body.rs")
|
||||
for field in ("source", "cache_effective_enabled", "transform_effective_enabled"):
|
||||
assert f"pub {field}: AtomicU8" in exchange
|
||||
assert f"pub {field}: Mutex" not in exchange
|
||||
assert "exchange.set_source(" in src("src/proxy/forward/route_cache.rs")
|
||||
assert "exchange.set_cache_enabled(" in src("src/proxy/forward/web_source.rs")
|
||||
assert "self.live.receiver_count() != 0" in src("src/logging/format.rs")
|
||||
assert "fn route_handles_reuse_snapshot_ownership_without_cloning_compiled_routes" in src("src/config/tests.rs")
|
||||
assert "fn single_backend_fast_path_observes_capacity_and_health_without_affinity_cookie" in src("src/balance/tests.rs")
|
||||
assert "fn atomic_exchange_tags_keep_original_observability_fields" in src("src/proxy/body/tests.rs")
|
||||
for path in (ROOT / "src").rglob("*.rs"):
|
||||
if "/tests/" in path.as_posix() or path.name == "tests.rs" or path.is_relative_to(ROOT / "tests"):
|
||||
continue
|
||||
assert len(path.read_text().splitlines()) <= 500, path
|
||||
assert 'version = "0.34.0"' in src("Cargo.toml")
|
||||
assert "max_idle_per_host: 4" in src("src/balance/model.rs")
|
||||
assert "pool_recycle_requests: 25_000" in src("src/balance/model.rs")
|
||||
print("PASS 0.34.0 proxy hot-path source wiring, observability, preserved defaults and source-size limits (STATIC ONLY)")
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Offline Chromium test: sendfile toggle serializes in real admin bundle.
|
||||
|
||||
It uses simulated config and a mocked saveSection; never claims native
|
||||
sendfile execution, Rust compilation or live server acceptance.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import json
|
||||
import re
|
||||
from playwright.sync_api import sync_playwright
|
||||
from panel_html import render_admin_index
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
ROUTER = (ROOT / "src/admin/router.rs").read_text()
|
||||
start = re.search(r'fn admin_app_javascript\([^)]*\)[^{]*\{', ROUTER)
|
||||
assert start
|
||||
array = ROUTER[start.end():]
|
||||
array = array[:re.search(r'\]\s*\.join\("\\n"\)', array).start()]
|
||||
chunks = []
|
||||
for line in array.splitlines():
|
||||
line = line.strip()
|
||||
match = re.search(r'include_str!\("([^"]+)"\)', line)
|
||||
if match:
|
||||
chunks.append((ROOT / "src/admin" / match.group(1)).read_text())
|
||||
elif line == 'admin_vhosts_javascript(),':
|
||||
chunks.append('(() => {\n' + '\n'.join(
|
||||
(ROOT / 'src/admin/web/vhosts' / (f + '.js')).read_text()
|
||||
for f in ('core', 'protocol', 'health', 'rates', 'editor', 'render')) + '\n})();')
|
||||
elif line.startswith('"') and line.endswith('",'):
|
||||
chunks.append(json.loads(line[:-1]))
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(headless=True, executable_path='/usr/bin/chromium', args=['--no-sandbox'])
|
||||
for width in (375, 1440):
|
||||
page = browser.new_page(viewport={'width': width, 'height': 950})
|
||||
page.set_default_timeout(4500)
|
||||
errors = []
|
||||
page.on('pageerror', lambda err: errors.append(str(err)))
|
||||
page.set_content(render_admin_index(ROOT))
|
||||
page.add_style_tag(content=(ROOT / 'src/admin/web/style.css').read_text())
|
||||
page.add_script_tag(content='\n'.join(chunks))
|
||||
page.evaluate('''() => {
|
||||
envelope = {revision: 10, config: {web_services: [{
|
||||
id: 'site-A', name: 'Static Site', document_root: '/srv/static',
|
||||
index: ['index.html'], php: {enabled: false}
|
||||
}], vhosts: [{id: 'vhost-A', keepalive: {max_connections: 8}}], php_fpm_profiles: []}};
|
||||
currentPanel = 'web-server';
|
||||
document.documentElement.classList.remove('app-loading', 'app-startup-failed');
|
||||
document.getElementById('login').hidden = true;
|
||||
document.getElementById('workspace').hidden = false;
|
||||
document.getElementById('panel-web-server').hidden = false;
|
||||
window.__saved = [];
|
||||
saveSection = async (section, value) => {
|
||||
window.__saved.push({section, value: structuredClone(value)});
|
||||
if (section === 'web-services') envelope.config.web_services = structuredClone(value);
|
||||
return true;
|
||||
};
|
||||
window.rustProxyWebServer.render();
|
||||
}''')
|
||||
page.evaluate("document.querySelector('#web-service-list .entity-actions button').click()")
|
||||
assert page.locator('#web-service-sendfile').input_value() == 'off'
|
||||
page.evaluate("document.getElementById('web-service-sendfile').value = 'auto'")
|
||||
page.evaluate('''() => { const form = document.getElementById('web-service-form'); if (!form.checkValidity()) throw new Error('invalid fields: ' + [...form.elements].filter(e=>!e.checkValidity()).map(e=>e.id).join(', ')); form.requestSubmit(); }''')
|
||||
page.wait_for_function('window.__saved.length === 1')
|
||||
result = page.evaluate('''() => ({
|
||||
saved: window.__saved[0],
|
||||
cacheStillUnrelated: envelope.config.vhosts[0].keepalive.max_connections === 8,
|
||||
closed: !document.getElementById('web-service-dialog').open
|
||||
})''')
|
||||
assert result['saved']['section'] == 'web-services', result
|
||||
assert result['saved']['value'][0]['sendfile'] == 'auto', result
|
||||
assert result['saved']['value'][0]['document_root'] == '/srv/static', result
|
||||
assert result['cacheStillUnrelated'] and result['closed'], result
|
||||
page.evaluate("document.querySelector('#web-service-list .entity-actions button').click()")
|
||||
assert page.locator('#web-service-sendfile').input_value() == 'auto'
|
||||
page.evaluate("document.getElementById('web-service-sendfile').value = 'off'")
|
||||
page.evaluate('''() => { const form = document.getElementById('web-service-form'); if (!form.checkValidity()) throw new Error('invalid fields: ' + [...form.elements].filter(e=>!e.checkValidity()).map(e=>e.id).join(', ')); form.requestSubmit(); }''')
|
||||
page.wait_for_function('window.__saved.length === 2')
|
||||
assert page.evaluate('envelope.config.web_services[0].sendfile') == 'off'
|
||||
assert not errors, errors
|
||||
print(f'PASS simulated panel sendfile off -> auto -> off config save at {width}px')
|
||||
browser.close()
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
"""RustProxy 0.34.0 sendfile source-wiring assertions ONLY, not native tests."""
|
||||
from pathlib import Path
|
||||
import json
|
||||
import re
|
||||
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
get = lambda path: (root / path).read_text()
|
||||
|
||||
model = get('src/web_server/config/model.rs')
|
||||
assert 'pub enum SendfileMode' in model and 'sendfile: SendfileMode::Off' in model
|
||||
assert 'pub sendfile: SendfileMode' in model
|
||||
assert 'sendfile: self.sendfile' in get('src/web_server/config/compile.rs')
|
||||
assert 'pub sendfile: SendfileMode' in get('src/web_server/config/validation.rs')
|
||||
assert 'service.sendfile = crate::web_server::SendfileMode::Off;' in get('src/runtime/types.rs')
|
||||
source = get('src/proxy/forward/web_source.rs')
|
||||
for guard in ('!enabled && identity_request', 'request_method == Method::GET',
|
||||
'response.status() == StatusCode::OK', 'content-encoding',
|
||||
'transfer-encoding', 'content-range', 'candidate.length',
|
||||
'http::Version::HTTP_11'):
|
||||
assert guard in source, guard
|
||||
assert 'content_encoding.is_none()' in get('src/web_server/response/file.rs')
|
||||
assert 'single_range.is_none()' in get('src/web_server/response/file.rs')
|
||||
assert 'opened.file.try_clone()' in get('src/web_server/response/file.rs')
|
||||
bridge = get('src/server/sendfile.rs')
|
||||
for item in ('libc::sendfile(', 'MAX_PENDING: usize = 8', 'MIN_SIZE: u64 = 64 * 1024',
|
||||
'registry.slots.is_empty()', 'native_sendfile_transfers_exact_file',
|
||||
'sendfile placeholder did not match', 'UnexpectedEof'):
|
||||
assert item in bridge, item
|
||||
assert 'pub(crate) mod sendfile' in get('src/server.rs')
|
||||
assert 'SendfileIo::new(stream)' in get('src/server/tls_runtime.rs')
|
||||
assert 'sendfile_slots' in get('src/server/http1_connection.rs')
|
||||
js = get('src/admin/web/web-server.js')
|
||||
html = get('src/admin/web/index.html')
|
||||
assert '"web-service-sendfile"' in js and 'sendfile: "off"' in js
|
||||
assert 'sendfile: $("web-service-sendfile").value' in js
|
||||
assert html.count('id="web-service-sendfile"') == 1
|
||||
assert 'value="auto"' in html
|
||||
for locale in ('en_US', 'pl_pl'):
|
||||
keys = json.loads(get(f'langs/{locale}.json'))['translations']
|
||||
assert all(k in keys for k in ('webServiceSendfile', 'webServiceSendfileHelp', 'webServiceSendfileAuto'))
|
||||
api = json.loads(get('src/admin/openapi.json'))
|
||||
assert 'sendfile' in json.dumps(api)
|
||||
print('PASS 0.34.0 sendfile source guards, default OFF, Linux syscall, UI, translations, API and scoped cache (STATIC ONLY)')
|
||||
Reference in new issue
Block a user