Skip to content
File

Blob: fuzzilli/d1-mock.js

javascript103 lines
1// Based on edgeworker D1 mock implementation with chaos
2const MOCK_USER_ROWS = {
3 1: { user_id: 1, name: 'Albert Ross', home: 'sky', features: 'wingspan' },
4 2: { user_id: 2, name: 'Al Dente', home: 'bowl', features: 'mouthfeel' },
5};
6 
7function shouldChaos() {
8 return Math.random() < 0.15; // 15% chaos for D1
9}
10 
11function getChaoticD1Response() {
12 const chaos = Math.random();
13 if (chaos < 0.25) {
14 // Database locked
15 return Response.json(
16 { error: 'database is locked', success: false },
17 { status: 500 }
18 );
19 } else if (chaos < 0.45) {
20 // Connection limit exceeded
21 return Response.json(
22 { error: 'too many connections', success: false },
23 { status: 503 }
24 );
25 } else if (chaos < 0.65) {
26 // Malformed response (missing success field)
27 return Response.json({ results: [], meta: { served_by: 'chaos' } });
28 } else if (chaos < 0.85) {
29 // SQL constraint violation
30 return Response.json(
31 {
32 error: 'UNIQUE constraint failed: users.email',
33 success: false,
34 },
35 { status: 400 }
36 );
37 } else {
38 // Completely wrong JSON structure
39 return Response.json({ chaos: true, random_field: 'unexpected' });
40 }
41}
42 
43function mockQuery({ sql, params = [] }) {
44 // Occasional chaos even in successful queries
45 if (shouldChaos()) {
46 if (Math.random() < 0.5) {
47 throw new Error('Random SQL execution error');
48 }
49 }
50 
51 switch (sql.trim()) {
52 case 'select 1;':
53 case 'SELECT 1':
54 return ok({ 1: 1 });
55 case 'select * from users;':
56 return ok(...Object.values(MOCK_USER_ROWS));
57 case 'select * from users where user_id = ?;':
58 return ok(MOCK_USER_ROWS[params[0]]);
59 default:
60 return ok(); // Empty result for unknown queries
61 }
62}
63 
64function ok(...results) {
65 return {
66 success: true,
67 results,
68 meta: { duration: Math.random() * 0.1, served_by: 'd1-mock' }, // Random duration
69 };
70}
71 
72export default {
73 async fetch(request, env, ctx) {
74 // Random top-level chaos
75 if (shouldChaos()) {
76 return getChaoticD1Response();
77 }
78 
79 try {
80 const { pathname } = new URL(request.url);
81 
82 if (
83 request.method === 'POST' &&
84 (pathname.startsWith('/query') || pathname.startsWith('/execute'))
85 ) {
86 const body = await request.json();
87 return Response.json(
88 Array.isArray(body)
89 ? body.map((query) => mockQuery(query))
90 : mockQuery(body)
91 );
92 }
93 
94 return new Response('D1 mock ready', { status: 200 });
95 } catch (err) {
96 return Response.json(
97 { error: err.message, success: false },
98 { status: 500 }
99 );
100 }
101 },
102};