72 lines
3.8 KiB
Python
72 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Exact production stop/start/process-slot functions with retained-resource doubles."""
|
|
from pathlib import Path
|
|
import re
|
|
import subprocess
|
|
import tempfile
|
|
root=Path(__file__).resolve().parents[2]
|
|
source=(root/'src/ssh_transport.c').read_text()
|
|
def function(name):
|
|
m=re.search(r'^static [^\n]+\b'+name+r'\([^;]*?\n\{.*?^\}',source,re.M|re.S)
|
|
assert m,name
|
|
return m.group()+'\n'
|
|
fakes=r'''
|
|
#include <assert.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#define SSH_TRANSPORT_MAX_SESSIONS 2
|
|
#define SSH_TRANSPORT_SESSION_FREE 0
|
|
#define SSH_TRANSPORT_SESSION_CLOSING 3
|
|
#define SSH_TRANSPORT_SESSION_HANDSHAKE 1
|
|
#define SSH_TRANSPORT_SESSION_ACTIVE 2
|
|
#define ESP_OK 0
|
|
#define ESP_FAIL 1
|
|
#define ESP_ERR_TIMEOUT 2
|
|
#define ESP_ERR_INVALID_STATE 3
|
|
#define pdMS_TO_TICKS(n) (n)
|
|
typedef int esp_err_t;
|
|
typedef struct { int state; bool close_requested; } ssh_slot_t;
|
|
static ssh_slot_t s_slots[2];
|
|
static void *s_context;
|
|
static int s_listen_fd=-1, s_lock;
|
|
static unsigned depth, frees, creates;
|
|
static bool s_running, s_cleanup_pending, cleanup_fail, listener_fail;
|
|
#define taskENTER_CRITICAL(p) do { (void)(p); assert(!depth++); } while(0)
|
|
#define taskEXIT_CRITICAL(p) do { (void)(p); assert(!--depth); } while(0)
|
|
static void wolfSSH_CTX_free(void *p) { assert(!depth && p==s_context); for(unsigned i=0;i<2;++i) assert(!s_slots[i].state); ++frees; }
|
|
static void close_socket(int *fd) { assert(!depth); *fd=-1; }
|
|
static void vTaskDelay(unsigned n) { (void)n; assert(!depth); }
|
|
static void request_slot_close(ssh_slot_t *s,bool revoked) { (void)revoked; if(s->state)s->close_requested=true; }
|
|
static bool cleanup_slot(ssh_slot_t *s) { if(cleanup_fail)return false; s->state=0;return true; }
|
|
static void publish_slot(ssh_slot_t *s,size_t i) { (void)s;(void)i; }
|
|
static bool consume_external_close(ssh_slot_t *s,size_t i) { (void)s;(void)i;return false; }
|
|
static void process_handshake(ssh_slot_t *s,size_t i) { (void)s;(void)i;assert(0); }
|
|
static void process_active(ssh_slot_t *s,size_t i) { (void)s;(void)i;assert(0); }
|
|
static esp_err_t create_context(void) { assert(!s_context && !depth); ++creates;s_context=(void *)1;return ESP_OK; }
|
|
static esp_err_t create_listener(void) { if(listener_fail)return ESP_FAIL;s_listen_fd=22;return ESP_OK; }
|
|
'''
|
|
tests=r'''
|
|
int main(void) {
|
|
assert(start_runtime()==ESP_OK && creates==1);
|
|
assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==1 && !frees);
|
|
s_slots[0].state=2;cleanup_fail=true;
|
|
assert(stop_runtime()==ESP_ERR_TIMEOUT && s_context && !frees && s_listen_fd==-1);
|
|
s_cleanup_pending=true;s_running=false;
|
|
assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==1);
|
|
process_slots();assert(s_context && s_cleanup_pending && !frees);
|
|
cleanup_fail=false;process_slots();assert(!s_context && !s_cleanup_pending && frees==1);
|
|
process_slots();assert(frees==1);
|
|
assert(start_runtime()==ESP_OK && creates==2);assert(stop_runtime()==ESP_OK && frees==2);
|
|
listener_fail=true;assert(start_runtime()==ESP_FAIL && !s_context && frees==3 && s_listen_fd==-1);
|
|
s_slots[1].state=2;assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==3);s_slots[1].state=0;
|
|
s_listen_fd=22;assert(start_runtime()==ESP_ERR_INVALID_STATE && creates==3);
|
|
puts("PASS SSH actual runtime stop failure retains context, rejects orphan overwrite, owner retires only after all slots free, failed listener frees context exactly once");
|
|
}
|
|
'''
|
|
with tempfile.TemporaryDirectory(prefix='ssh-runtime-') as directory:
|
|
out=Path(directory)
|
|
(out/'test.c').write_text(fakes+''.join(function(n) for n in ('start_runtime','stop_runtime','process_slots'))+tests)
|
|
subprocess.run(['cc','-std=c11','-Wall','-Wextra','-Werror',str(out/'test.c'),'-o',str(out/'test')],check=True,timeout=30)
|
|
subprocess.run([str(out/'test')],check=True,timeout=10)
|