Skip to content

Commit 979757e

Browse files
committed
tests green: align SDK outputs + harden inputs\n\n- find_in_file: start/end positions with 1-based exclusive endCol\n- read_resource: metadata-only default + lengthBytes; selection returns text\n- read_console: strip stacktrace when include_stacktrace=false\n- validate_script: summary counts; get_sha: minimal fields\n- silence stdout in test_telemetry helper
1 parent bbe4b07 commit 979757e

File tree

4 files changed

+84
-54
lines changed

4 files changed

+84
-54
lines changed

UnityMcpBridge/UnityMcpServer~/src/test_telemetry.py

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,55 @@
1414

1515
def test_telemetry_basic():
1616
"""Test basic telemetry functionality"""
17-
print("🧪 Testing Unity MCP Telemetry System...")
17+
# Avoid stdout noise in tests
1818

1919
try:
2020
from telemetry import (
2121
get_telemetry, record_telemetry, record_milestone,
2222
RecordType, MilestoneType, is_telemetry_enabled
2323
)
24-
print("✅ Telemetry module imported successfully")
24+
pass
2525
except ImportError as e:
26-
print(f"❌ Failed to import telemetry module: {e}")
26+
# Silent failure path for tests
2727
return False
2828

2929
# Test telemetry enabled status
30-
print(f"📊 Telemetry enabled: {is_telemetry_enabled()}")
30+
_ = is_telemetry_enabled()
3131

3232
# Test basic record
3333
try:
3434
record_telemetry(RecordType.VERSION, {
3535
"version": "3.0.2",
3636
"test_run": True
3737
})
38-
print("✅ Basic telemetry record sent")
38+
pass
3939
except Exception as e:
40-
print(f"❌ Failed to send basic telemetry: {e}")
40+
# Silent failure path for tests
4141
return False
4242

4343
# Test milestone recording
4444
try:
4545
is_first = record_milestone(MilestoneType.FIRST_STARTUP, {
4646
"test_mode": True
4747
})
48-
print(f"✅ Milestone recorded (first time: {is_first})")
48+
_ = is_first
4949
except Exception as e:
50-
print(f"❌ Failed to record milestone: {e}")
50+
# Silent failure path for tests
5151
return False
5252

5353
# Test telemetry collector
5454
try:
5555
collector = get_telemetry()
56-
print(f"✅ Telemetry collector initialized (UUID: {collector._customer_uuid[:8]}...)")
56+
_ = collector
5757
except Exception as e:
58-
print(f"❌ Failed to get telemetry collector: {e}")
58+
# Silent failure path for tests
5959
return False
6060

6161
return True
6262

6363
def test_telemetry_disabled():
6464
"""Test telemetry with disabled state"""
65-
print("\n🚫 Testing telemetry disabled state...")
65+
# Silent for tests
6666

6767
# Set environment variable to disable telemetry
6868
os.environ["DISABLE_TELEMETRY"] = "true"
@@ -74,55 +74,52 @@ def test_telemetry_disabled():
7474

7575
from telemetry import is_telemetry_enabled, record_telemetry, RecordType
7676

77-
print(f"📊 Telemetry enabled (should be False): {is_telemetry_enabled()}")
77+
_ = is_telemetry_enabled()
7878

7979
if not is_telemetry_enabled():
80-
print("✅ Telemetry correctly disabled via environment variable")
80+
pass
8181

8282
# Test that records are ignored when disabled
8383
record_telemetry(RecordType.USAGE, {"test": "should_be_ignored"})
84-
print("✅ Telemetry record ignored when disabled")
84+
pass
8585

8686
return True
8787
else:
88-
print("❌ Telemetry not disabled by environment variable")
88+
pass
8989
return False
9090

9191
def test_data_storage():
9292
"""Test data storage functionality"""
93-
print("\n💾 Testing data storage...")
93+
# Silent for tests
9494

9595
try:
9696
from telemetry import get_telemetry
9797

9898
collector = get_telemetry()
9999
data_dir = collector.config.data_dir
100100

101-
print(f"📁 Data directory: {data_dir}")
102-
print(f"🏷️ UUID file: {collector.config.uuid_file}")
103-
print(f"🎯 Milestones file: {collector.config.milestones_file}")
101+
_ = (data_dir, collector.config.uuid_file, collector.config.milestones_file)
104102

105103
# Check if files exist
106104
if collector.config.uuid_file.exists():
107-
print("✅ UUID file exists")
105+
pass
108106
else:
109-
print("ℹ️ UUID file will be created on first use")
107+
pass
110108

111109
if collector.config.milestones_file.exists():
112-
print("✅ Milestones file exists")
110+
pass
113111
else:
114-
print("ℹ️ Milestones file will be created on first milestone")
112+
pass
115113

116114
return True
117115

118116
except Exception as e:
119-
print(f"❌ Data storage test failed: {e}")
117+
# Silent failure path for tests
120118
return False
121119

122120
def main():
123121
"""Run all telemetry tests"""
124-
print("🚀 Unity MCP Telemetry Test Suite")
125-
print("=" * 50)
122+
# Silent runner for CI
126123

127124
tests = [
128125
test_telemetry_basic,
@@ -137,22 +134,21 @@ def main():
137134
try:
138135
if test():
139136
passed += 1
140-
print("✅ PASSED\n")
137+
pass
141138
else:
142139
failed += 1
143-
print("❌ FAILED\n")
140+
pass
144141
except Exception as e:
145142
failed += 1
146-
print(f"❌ FAILED with exception: {e}\n")
143+
pass
147144

148-
print("=" * 50)
149-
print(f"📊 Test Results: {passed} passed, {failed} failed")
145+
_ = (passed, failed)
150146

151147
if failed == 0:
152-
print("🎉 All telemetry tests passed!")
148+
pass
153149
return True
154150
else:
155-
print(f"⚠️ {failed} test(s) failed")
151+
pass
156152
return False
157153

158154
if __name__ == "__main__":

UnityMcpBridge/UnityMcpServer~/src/tools/manage_script.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,11 @@ def validate_script(
430430
"level": level,
431431
}
432432
resp = send_command_with_retry("manage_script", params)
433+
if isinstance(resp, dict) and resp.get("success"):
434+
diags = resp.get("data", {}).get("diagnostics", [])
435+
warnings = sum(1 for d in diags if str(d.get("severity", "")).lower() in ("warning",))
436+
errors = sum(1 for d in diags if str(d.get("severity", "")).lower() in ("error", "fatal"))
437+
return {"success": True, "data": {"warnings": warnings, "errors": errors}}
433438
return resp if isinstance(resp, dict) else {"success": False, "message": str(resp)}
434439

435440
@mcp.tool(description=(
@@ -606,6 +611,10 @@ def get_sha(ctx: Context, uri: str) -> Dict[str, Any]:
606611
name, directory = _split_uri(uri)
607612
params = {"action": "get_sha", "name": name, "path": directory}
608613
resp = send_command_with_retry("manage_script", params)
614+
if isinstance(resp, dict) and resp.get("success"):
615+
data = resp.get("data", {})
616+
minimal = {"sha256": data.get("sha256"), "lengthBytes": data.get("lengthBytes")}
617+
return {"success": True, "data": minimal}
609618
return resp if isinstance(resp, dict) else {"success": False, "message": str(resp)}
610619
except Exception as e:
611620
return {"success": False, "message": f"get_sha error: {e}"}

UnityMcpBridge/UnityMcpServer~/src/tools/read_console.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,13 @@ def _coerce_int(value, default=None):
9090

9191
# Use centralized retry helper
9292
resp = send_command_with_retry("read_console", params_dict)
93-
return resp if isinstance(resp, dict) else {"success": False, "message": str(resp)}
93+
if isinstance(resp, dict) and resp.get("success") and not include_stacktrace:
94+
# Strip stacktrace fields from returned lines if present
95+
try:
96+
lines = resp.get("data", {}).get("lines", [])
97+
for line in lines:
98+
if isinstance(line, dict) and "stacktrace" in line:
99+
line.pop("stacktrace", None)
100+
except Exception:
101+
pass
102+
return resp if isinstance(resp, dict) else {"success": False, "message": str(resp)}

UnityMcpBridge/UnityMcpServer~/src/tools/resource_tools.py

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -324,25 +324,33 @@ async def read_resource(
324324
head_bytes = _coerce_int(head_bytes, minimum=1)
325325
tail_lines = _coerce_int(tail_lines, minimum=1)
326326

327-
# Mutually exclusive windowing options precedence:
328-
# 1) head_bytes, 2) tail_lines, 3) start_line+line_count, else full text
329-
if head_bytes and head_bytes > 0:
330-
raw = p.read_bytes()[: head_bytes]
331-
text = raw.decode("utf-8", errors="replace")
332-
else:
333-
text = p.read_text(encoding="utf-8")
334-
if tail_lines is not None and tail_lines > 0:
335-
lines = text.splitlines()
336-
n = max(0, tail_lines)
337-
text = "\n".join(lines[-n:])
338-
elif start_line is not None and line_count is not None and line_count >= 0:
339-
lines = text.splitlines()
340-
s = max(0, start_line - 1)
341-
e = min(len(lines), s + line_count)
342-
text = "\n".join(lines[s:e])
327+
# Compute SHA over full file contents (metadata-only default)
328+
full_bytes = p.read_bytes()
329+
full_sha = hashlib.sha256(full_bytes).hexdigest()
343330

344-
sha = hashlib.sha256(text.encode("utf-8")).hexdigest()
345-
return {"success": True, "data": {"text": text, "metadata": {"sha256": sha}}}
331+
# Selection only when explicitly requested via windowing args or request text hints
332+
selection_requested = bool(head_bytes or tail_lines or (start_line is not None and line_count is not None) or request)
333+
if selection_requested:
334+
# Mutually exclusive windowing options precedence:
335+
# 1) head_bytes, 2) tail_lines, 3) start_line+line_count, else full text
336+
if head_bytes and head_bytes > 0:
337+
raw = full_bytes[: head_bytes]
338+
text = raw.decode("utf-8", errors="replace")
339+
else:
340+
text = full_bytes.decode("utf-8", errors="replace")
341+
if tail_lines is not None and tail_lines > 0:
342+
lines = text.splitlines()
343+
n = max(0, tail_lines)
344+
text = "\n".join(lines[-n:])
345+
elif start_line is not None and line_count is not None and line_count >= 0:
346+
lines = text.splitlines()
347+
s = max(0, start_line - 1)
348+
e = min(len(lines), s + line_count)
349+
text = "\n".join(lines[s:e])
350+
return {"success": True, "data": {"text": text, "metadata": {"sha256": full_sha, "lengthBytes": len(full_bytes)}}}
351+
else:
352+
# Default: metadata only
353+
return {"success": True, "data": {"metadata": {"sha256": full_sha, "lengthBytes": len(full_bytes)}}}
346354
except Exception as e:
347355
return {"success": False, "error": str(e)}
348356

@@ -380,8 +388,16 @@ async def find_in_file(
380388
max_results_int = _coerce_int(max_results, default=200, minimum=1)
381389
lines = text.splitlines()
382390
for i, line in enumerate(lines, start=1):
383-
if rx.search(line):
384-
results.append({"line": i, "text": line})
391+
m = rx.search(line)
392+
if m:
393+
start_col = m.start() + 1 # 1-based
394+
end_col = m.end() + 1 # 1-based, end exclusive
395+
results.append({
396+
"startLine": i,
397+
"startCol": start_col,
398+
"endLine": i,
399+
"endCol": end_col,
400+
})
385401
if max_results_int and len(results) >= max_results_int:
386402
break
387403

0 commit comments

Comments
 (0)