This commit is contained in:
KIM SU BO committed 2026-10-06 13:23:42 +09:00
1 parent 618ba02cb9
commit 83278b2998
124 files changed
-49298

No files matched your search

-126
View File
@@ -1,126 +0,0 @@
"""
DAT10: 7일간 통신 단절 후 대량 재고 트랜잭션 일괄 동기화 스트레스 테스트
- 10,000건 대량 트랜잭션 배치 고속 처리 검증
- 동시 다발적 P2P / CRDT 동기화 부하 테스트
- 메모리 누수 및 처리 지연 시간(Throughput) 프로파일링
- 시스템 다운 0건, 데이터 유실률 0% 달성 검증
"""
import time
import random
import uuid
import datetime
import tracemalloc
from typing import List, Dict, Any
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from src.preprocess.dat10_preprocessor import TacticalDataPreprocessor
from src.models.dat10_advanced_detector import AdvancedCRDTSyncEngine
from src.verification.dat10_confidence_engine import TacticalConfidenceEngine, MerkleTreeVerifier
def generate_stress_transactions(count: int = 10000) -> List[Dict[str, Any]]:
txs = []
nsn_list = [
"1005-01-584-1234", "2530-01-450-8899", "8970-01-345-6789",
"9130-01-222-3333", "5998-01-777-8888", "2920-01-111-2222"
]
terminals = [f"TERM-A{i:03d}" for i in range(1, 21)]
tx_types = ["ISSUE", "RECEIPT", "TRANSFER", "FIELD_CONSUME"]
last_hash = "0" * 64
base_time = datetime.datetime.utcnow() - datetime.timedelta(days=7)
for i in range(count):
nsn = random.choice(nsn_list)
term = random.choice(terminals)
qty = random.randint(1, 500)
stock = max(0, 50000 - i * 3)
ttime = (base_time + datetime.timedelta(seconds=i * 60)).isoformat() + "Z"
tx_id = f"TX-STRESS-{i:06d}"
payload = f"{tx_id}|{term}|{nsn}|ISSUE|{qty}|{stock}|{i+1}|{last_hash}"
import hashlib
rec_hash = hashlib.sha256(payload.encode("utf-8")).hexdigest()
txs.append({
"transaction_id": tx_id,
"terminal_id": term,
"unit_id": "BN-01",
"nsn_code": nsn,
"item_name": "Test Item",
"supply_class": "Class_V",
"tx_type": "ISSUE",
"quantity": qty,
"current_stock": stock,
"unit_cost": 15.0,
"comms_status": "OFFLINE_LOCAL",
"grid_coords": "52SDJ12345678",
"weather_condition": "CLEAR",
"lamport_timestamp": i + 1,
"timestamp_utc": ttime,
"prev_hash": last_hash,
"record_hash": rec_hash
})
last_hash = rec_hash
return txs
def run_stress_test(count: int = 10000):
print(f"=== [DAT10] 7일 통신 단절 10,000건 대량 동기화 스트레스 테스트 시작 ===")
# 메모리 측정 시작
tracemalloc.start()
start_time = time.time()
# 1. 테스트 데이터셋 생성
t0 = time.time()
raw_data = generate_stress_transactions(count)
gen_time = time.time() - t0
print(f"[1/4] 데이터 생성 완료: {count}건 ({gen_time:.2f}초)")
# 2. 고속 전처리 파이프라인 부하 테스트
t1 = time.time()
preprocessor = TacticalDataPreprocessor(":memory:")
result = preprocessor.process_batch(raw_data)
prep_time = time.time() - t1
prep_throughput = count / prep_time
print(f"[2/4] 전처리 파이프라인 완료: {prep_time:.2f}초 (처리량: {prep_throughput:.1f} 건/초, 유효건수: {result['valid_records']})")
# 3. CRDT 양방향 동기화 부하 테스트
t2 = time.time()
engine_a = AdvancedCRDTSyncEngine("TERM-A101")
engine_b = AdvancedCRDTSyncEngine("TERM-B202")
for rec in raw_data[:count]:
engine_a.increment(rec["nsn_code"], rec["quantity"])
engine_b.decrement(rec["nsn_code"], rec["quantity"] // 2)
engine_a.merge(engine_b.pn_counters)
crdt_time = time.time() - t2
print(f"[3/4] CRDT 동기화 완료: {crdt_time:.2f}초")
# 4. 머클 트리 및 무결성 검증 부하 테스트
t3 = time.time()
hashes = [r["record_hash"] for r in raw_data]
merkle = MerkleTreeVerifier(hashes)
merkle_time = time.time() - t3
print(f"[4/4] 머클 트리 무결성 검증 완료: Root={merkle.root[:16]}... ({merkle_time:.2f}초)")
total_time = time.time() - start_time
current_mem, peak_mem = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"\n=== [스트레스 테스트 종합 결과] ===")
print(f"- 총 처리 건수: {count:,} 건")
print(f"- 총 소요 시간: {total_time:.2f} 초 (전처리 속도: {prep_throughput:,.1f} 건/초)")
print(f"- 최대 메모리 사용량: {peak_mem / (1024 * 1024):.2f} MB")
print(f"- 데이터 유실률: 0.00% (유실 0건)")
print(f"- 시스템 다운 및 예외 발생: 0건 (PASS)")
assert result["valid_records"] == count
assert prep_throughput >= 1000.0, "처리 속도가 1,000건/초 기준에 미달합니다."
print(">>> [PASS] 모든 스트레스 테스트 기준을 만족하였습니다.")
if __name__ == "__main__":
run_stress_test(10000)
-69
View File
@@ -1,69 +0,0 @@
"""
DAT10: 전체 유닛 및 통합 테스트 스위트 (pytest 호환)
"""
import pytest
import os
import sys
import pandas as pd
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from src.preprocess.dat10_preprocessor import TacticalDataPreprocessor
from src.models.dat10_baseline_model import P2PInventoryBaselineSync
from src.models.dat10_advanced_detector import AdvancedCRDTSyncEngine, AdvancedSupplyChainDisasterDetector
from src.verification.dat10_confidence_engine import TacticalConfidenceEngine, MerkleTreeVerifier
from src.hitl.dat10_approval_workflow import HITLApprovalWorkflow
def test_preprocessor_validation():
prep = TacticalDataPreprocessor(":memory:")
raw = [{
"transaction_id": "TX-TEST-001",
"terminal_id": "TERM-A101",
"unit_id": "BN-01",
"nsn_code": "1005-01-584-1234",
"quantity": -50, # 음수 -> 보정되어야 함
"tx_type": "ISSUE"
}]
res = prep.process_batch(raw)
assert res["total_processed"] == 1
assert res["records"][0]["quantity"] == 50
def test_crdt_pn_counter():
engine_a = AdvancedCRDTSyncEngine("NODE_A")
engine_b = AdvancedCRDTSyncEngine("NODE_B")
engine_a.increment("ITEM_1", 100)
engine_a.decrement("ITEM_1", 20)
engine_b.increment("ITEM_1", 50)
engine_b.decrement("ITEM_1", 10)
engine_a.merge(engine_b.pn_counters)
assert engine_a.value("ITEM_1") == 120
def test_confidence_engine():
conf = TacticalConfidenceEngine()
tx = {
"transaction_id": "TX-01",
"is_valid": 1,
"lamport_timestamp": 5,
"grid_coords": "52SDJ12345678",
"stock_after": 500
}
eval_res = conf.evaluate_confidence(tx)
assert eval_res["confidence_score"] >= 0.85
assert eval_res["confidence_grade"] == "HIGH"
def test_merkle_tree():
hashes = ["a"*64, "b"*64, "c"*64, "d"*64]
merkle = MerkleTreeVerifier(hashes)
assert len(merkle.root) == 64
def test_hitl_workflow():
hitl = HITLApprovalWorkflow(":memory:")
res = hitl.resolve_conflict("CONF-01", "1005-01", "APPROVE_LOCAL", "Officer", "Verified", 500)
assert res["status"] == "RESOLVED"
assert len(hitl.get_audit_trail()) == 1
if __name__ == "__main__":
pytest.main(["-v", __file__])