File size: 7,572 Bytes
35765b5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
"""
Dev B Test Suite - Run with: .venv/Scripts/python test_devb.py
"""

import asyncio
import sys
sys.path.insert(0, '.')

from app.llm import generate_documentation, synthesize_answer, get_embedding
from app.vectorstore import init_vectorstore, add_embedding, search, count_embeddings, delete_by_project

# Test counters
passed = 0
failed = 0


def test(name, condition, details=""):
    global passed, failed
    if condition:
        print(f"  [PASS] {name}")
        passed += 1
    else:
        print(f"  [FAIL] {name} - {details}")
        failed += 1


async def test_llm():
    print("\n[1/4] Testing LLM Client (llm.py)")
    print("-" * 40)

    # Test 1: get_embedding
    try:
        emb = await get_embedding("test embedding")
        test("get_embedding returns list", isinstance(emb, list))
        test("get_embedding returns 768 dims", len(emb) == 768, f"got {len(emb)}")
        test("get_embedding returns floats", isinstance(emb[0], float))
    except Exception as e:
        test("get_embedding", False, str(e))

    # Test 2: generate_documentation
    try:
        doc = await generate_documentation(
            task_title="Setup API",
            what_i_did="Created REST endpoints",
            code_snippet="@app.get('/api')"
        )
        test("generate_documentation returns dict", isinstance(doc, dict))
        test("generate_documentation has summary", "summary" in doc)
        test("generate_documentation has details", "details" in doc)
        test("generate_documentation has tags", "tags" in doc and isinstance(doc["tags"], list))
    except Exception as e:
        test("generate_documentation", False, str(e))

    # Test 3: synthesize_answer
    try:
        answer = await synthesize_answer(
            context="Task completed: Built login system with JWT authentication",
            query="What authentication was implemented?"
        )
        test("synthesize_answer returns string", isinstance(answer, str))
        test("synthesize_answer not empty", len(answer) > 0)
    except Exception as e:
        test("synthesize_answer", False, str(e))


async def test_vectorstore():
    print("\n[2/4] Testing Vector Store (vectorstore.py)")
    print("-" * 40)

    # Test 1: init_vectorstore
    try:
        init_vectorstore()
        test("init_vectorstore succeeds", True)
    except Exception as e:
        test("init_vectorstore", False, str(e))
        return  # Can't continue without init

    # Clean up test data first
    try:
        delete_by_project("test-project-xyz")
    except:
        pass

    # Test 2: add_embedding
    try:
        emb = await get_embedding("Test document about Python programming")
        add_embedding(
            log_entry_id="test-entry-1",
            text="Test document about Python programming",
            embedding=emb,
            metadata={
                "project_id": "test-project-xyz",
                "user_id": "test-user",
                "task_id": "test-task",
                "created_at": "2024-01-01T00:00:00"
            }
        )
        test("add_embedding succeeds", True)
    except Exception as e:
        test("add_embedding", False, str(e))

    # Test 3: count_embeddings
    try:
        count = count_embeddings("test-project-xyz")
        test("count_embeddings returns int", isinstance(count, int))
        test("count_embeddings >= 1", count >= 1, f"got {count}")
    except Exception as e:
        test("count_embeddings", False, str(e))

    # Test 4: search
    try:
        query_emb = await get_embedding("Python")
        results = search(query_emb, "test-project-xyz", n_results=5)
        test("search returns list", isinstance(results, list))
        test("search finds results", len(results) > 0, "no results found")
        if results:
            test("search result has id", "id" in results[0])
            test("search result has metadata", "metadata" in results[0])
            test("search result has distance", "distance" in results[0])
    except Exception as e:
        test("search", False, str(e))

    # Test 5: delete_by_project
    try:
        delete_by_project("test-project-xyz")
        count_after = count_embeddings("test-project-xyz")
        test("delete_by_project removes data", count_after == 0, f"still has {count_after}")
    except Exception as e:
        test("delete_by_project", False, str(e))


async def test_full_pipeline():
    print("\n[3/4] Testing Full Pipeline")
    print("-" * 40)

    project_id = "pipeline-test-proj"

    # Clean up first
    try:
        delete_by_project(project_id)
    except:
        pass

    try:
        # Step 1: Generate documentation
        doc = await generate_documentation(
            task_title="Implement user registration",
            what_i_did="Added signup endpoint with email validation and password hashing",
            code_snippet="def register(email, password): ..."
        )
        test("Pipeline: doc generation", "summary" in doc and "details" in doc)

        # Step 2: Create embedding from doc
        text_to_embed = f"{doc['summary']} {doc['details']}"
        embedding = await get_embedding(text_to_embed)
        test("Pipeline: embedding created", len(embedding) == 768)

        # Step 3: Store in vectorstore
        add_embedding(
            log_entry_id="pipeline-log-1",
            text=text_to_embed,
            embedding=embedding,
            metadata={"project_id": project_id, "user_id": "dev1"}
        )
        test("Pipeline: stored in vectorstore", count_embeddings(project_id) == 1)

        # Step 4: Search for it
        query_emb = await get_embedding("user registration signup")
        results = search(query_emb, project_id)
        test("Pipeline: search finds it", len(results) > 0)

        # Step 5: Synthesize answer
        if results:
            context = results[0]["metadata"]["text"]
            answer = await synthesize_answer(context, "What was done for user registration?")
            test("Pipeline: answer synthesized", len(answer) > 20)

        # Cleanup
        delete_by_project(project_id)

    except Exception as e:
        test("Pipeline", False, str(e))


async def test_edge_cases():
    print("\n[4/4] Testing Edge Cases")
    print("-" * 40)

    # Test empty search
    try:
        init_vectorstore()
        emb = await get_embedding("random query")
        results = search(emb, "nonexistent-project-12345")
        test("Empty search returns empty list", results == [])
    except Exception as e:
        test("Empty search", False, str(e))

    # Test long text embedding
    try:
        long_text = "word " * 1000  # ~5000 chars
        emb = await get_embedding(long_text)
        test("Long text embedding works", len(emb) == 768)
    except Exception as e:
        test("Long text embedding", False, str(e))

    # Test special characters
    try:
        special_text = "Code: `const x = 'hello';` // comment <script>alert('xss')</script>"
        emb = await get_embedding(special_text)
        test("Special chars embedding works", len(emb) == 768)
    except Exception as e:
        test("Special chars embedding", False, str(e))


async def main():
    print("=" * 50)
    print("  DEV B TEST SUITE - Intelligence Layer")
    print("=" * 50)

    await test_llm()
    await test_vectorstore()
    await test_full_pipeline()
    await test_edge_cases()

    print("\n" + "=" * 50)
    print(f"  RESULTS: {passed} passed, {failed} failed")
    print("=" * 50)

    if failed > 0:
        sys.exit(1)


if __name__ == "__main__":
    asyncio.run(main())