File size: 6,323 Bytes
bc12c74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
Test the actual HTTP response flow as the OpenEnv validator would see it.
This simulates calling /step endpoint and checking JSON response.
"""

import json
import sys
from fastapi.testclient import TestClient
from server.app import app

client = TestClient(app)


def test_http_flow():
    """Test complete HTTP flow for reward responses."""
    print("="*80)
    print("HTTP RESPONSE FLOW TEST")
    print("="*80)
    
    failures = []
    
    # 1. Reset
    print("\n1. Calling /reset...")
    resp_reset = client.post("/reset")
    if resp_reset.status_code != 200:
        print(f"   [FAIL] Reset failed: {resp_reset.status_code}")
        print(f"   Response: {resp_reset.text}")
        return
    print(f"   [OK] Reset successful")
    
    #2. Step with fixed config for task1
    print("\n2. Calling /step with fixed config for task1_json...")
    step_payload = {
        "fixed_config": '{"name": "Alice", "age": 30, "email": "alice@example.com"}'
    }
    
    resp_step = client.post("/step", json=step_payload)
    if resp_step.status_code != 200:
        print(f"   [FAIL] Step failed: {resp_step.status_code}")
        print(f"   Response: {resp_step.text}")
        return
    
    print(f"   [OK] Step returned 200")
    
    try:
        response_json = resp_step.json()
        print(f"   JSON parsed successfully")
        print(f"   Response keys: {list(response_json.keys())}")
    except json.JSONDecodeError as e:
        print(f"   [FAIL] Failed to parse JSON: {e}")
        print(f"   Raw response: {resp_step.text}")
        failures.append("JSON parse failed")
        return
    
    # 3. Check reward field
    if "reward" not in response_json:
        print(f"   [FAIL] No 'reward' field in response")
        print(f"   Response: {response_json}")
        failures.append("Missing reward field")
        return
    
    reward = response_json["reward"]
    print(f"\n3. Reward value in response: {reward}")
    print(f"   Type: {type(reward).__name__}")
    print(f"   Repr: {repr(reward)}")
    
    # 4. Validate reward
    try:
        reward_float = float(reward)
        print(f"   Converted to float: {reward_float}")
    except (TypeError, ValueError) as e:
        print(f"   [FAIL] Cannot convert to float: {e}")
        failures.append(f"Reward not numeric: {reward}")
        return
    
    # 5. Check bounds
    if reward_float == float('inf') or reward_float == float('-inf'):
        print(f"   [FAIL] Reward is infinite")
        failures.append("Reward is infinite")
    elif reward_float != reward_float:  # NaN
        print(f"   [FAIL] Reward is NaN")
        failures.append("Reward is NaN")
    elif not (0.0 < reward_float < 1.0):
        print(f"   [FAIL] Reward {reward_float} out of bounds (0, 1)")
        failures.append(f"Out of bounds: {reward_float}")
    else:
        print(f"   [OK] Reward {reward_float} is in valid range (0, 1)")
    
    # 6. Check JSON serialization round-trip
    print(f"\n4. JSON serialization check...")
    json_str = json.dumps(response_json)
    print(f"   JSON string: {json_str[:100]}...")
    
    reparsed = json.loads(json_str)
    reparsed_reward = reparsed.get("reward")
    print(f"   After round-trip: {reparsed_reward}")
    print(f"   Type: {type(reparsed_reward).__name__}")
    
    if reparsed_reward != reward:
        print(f"   [WARN] Reward changed during round-trip: {reward} -> {reparsed_reward}")
    
    # Summary
    if failures:
        print(f"\n{'='*80}")
        print(f"[FAIL] Found {len(failures)} issues:")
        for f in failures:
            print(f"  - {f}")
        return False
    else:
        print(f"\n[OK] All HTTP response checks passed")
        return True


def test_all_tasks():
    """Test /step with perfect configs for all 7 tasks."""
    print("\n" + "="*80)
    print("TESTING ALL 7 TASKS VIA /step ENDPOINT")
    print("="*80)
    
    test_configs = {
        "task1_json": '{"name": "Alice", "age": 30, "email": "alice@example.com"}',
        "task2_yaml": "name: Alice\nage: 30\nemail: alice@example.com",
        "task3_dockerfile": "FROM python:3.9-slim\nRUN apt-get update\nEXPOSE 3000\nCMD [\"python\", \"app.py\"]",
        "task4_compose": "services:\n  web:\n    image: app\n    ports:\n      - '8080:3000'\n  db:\n    image: postgres",
        "task5_k8s": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: app-pod\nspec:\n  containers:\n    - name: app\n      image: app:latest",
        "task6_github_actions": "on: push\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout\n      - run: echo test",
        "task7_nginx": "server {\n  listen 80;\n  server_name example.com;\n  location / {\n    proxy_pass http://localhost:3000;\n  }\n}",
    }
    
    all_passed = True
    
    # Reset once
    client.post("/reset")
    
    for task_id, config in test_configs.items():
        print(f"\nTask: {task_id}")
        
        resp = client.post("/step", json={"fixed_config": config})
        
        if resp.status_code != 200:
            print(f"  [FAIL] Status {resp.status_code}: {resp.text[:100]}")
            all_passed = False
            continue
        
        try:
            data = resp.json()
            reward = data.get("reward")
            
            if reward is None:
                print(f"  [FAIL] No reward in response")
                all_passed = False
            else:
                reward_float = float(reward)
                if 0.0 < reward_float < 1.0:
                    print(f"  [OK] Reward: {reward}")
                else:
                    print(f"  [FAIL] Out of bounds: {reward_float}")
                    all_passed = False
        except Exception as e:
            print(f"  [FAIL] Exception: {e}")
            all_passed = False
    
    return all_passed


def main():
    try:
        # Test single flow
        passed = test_http_flow()
        
        if passed is not False:
            # Test all tasks
            all_passed = test_all_tasks()
        
        print("\n" + "="*80)
        print("HTTP FLOW TEST COMPLETE")
        print("="*80)
        
    except Exception as e:
        print(f"\n[EXCEPTION] {type(e).__name__}: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    main()