File size: 4,444 Bytes
f45e448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import fs from 'fs';

const API_BASE = 'http://localhost:3001/api';

async function login(email, password) {
  const res = await fetch(`${API_BASE}/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });
  const data = await res.json();
  if (!res.ok || !data.success) throw new Error(`Login failed: ${JSON.stringify(data)}`);
  return data.data.token;
}

async function register(email, password) {
  const res = await fetch(`${API_BASE}/auth/register`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password, emailCode: '123456' })
  });
  const data = await res.json();
  if (!res.ok || !data.success) {
    if (data.message === 'User already exists') {
      return await login(email, password);
    }
    throw new Error(`Register failed: ${JSON.stringify(data)}`);
  }
  return data.data.token;
}

async function createCourse(token, index) {
  const res = await fetch(`${API_BASE}/admin/courses`, {
    method: 'POST',
    headers: { 
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({
      title: `Stress Test Course ${index}`,
      description: `A course created for load testing ${index}`,
      coverImage: 'https://via.placeholder.com/150',
      driveLink: 'https://drive.google.com/example',
      price: 9.99,
      category: 'Testing'
    })
  });
  const data = await res.json();
  if (!res.ok) throw new Error(`Create course failed: ${JSON.stringify(data)}`);
  return data.data.id;
}

async function createOrder(token, courseId, price) {
  const res = await fetch(`${API_BASE}/orders/create`, {
    method: 'POST',
    headers: { 
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({ courseId, price })
  });
  const data = await res.json();
  if (!res.ok) throw new Error(`Create order failed: ${JSON.stringify(data)}`);
  return data.data.orderId;
}

async function preparePayment(token, orderId) {
  const res = await fetch(`${API_BASE}/payment/prepare`, {
    method: 'POST',
    headers: { 
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({ orderId: String(orderId), payType: 'wechat' })
  });
  const data = await res.json();
  if (!res.ok) throw new Error(`Prepare payment failed: ${JSON.stringify(data)}`);
  return data.data;
}

async function runTest() {
  console.log('Starting Load Test...');
  
  // 1. Admin login
  console.log('Logging in as admin...');
  const adminToken = await login('admin@example.com', '123456');
  
  // 2. Create courses
  const NUM_COURSES = 10;
  console.log(`Creating ${NUM_COURSES} courses...`);
  const courseIds = [];
  for (let i = 1; i <= NUM_COURSES; i++) {
    const id = await createCourse(adminToken, i);
    courseIds.push(id);
  }
  console.log(`Created course IDs: ${courseIds.join(', ')}`);

  // 3. Create users
  const NUM_USERS = 50;
  console.log(`Creating ${NUM_USERS} users...`);
  const userTokens = [];
  for (let i = 1; i <= NUM_USERS; i++) {
    const email = `loadtestuser${Date.now()}_${i}@example.com`;
    const token = await register(email, '123456');
    userTokens.push(token);
  }

  // 4. Stress test: all users try to buy all courses concurrently
  console.log(`Starting concurrent purchase stress test for ${NUM_USERS * NUM_COURSES} requests...`);
  const startTime = Date.now();
  let successCount = 0;
  let failCount = 0;
  
  const tasks = [];
  
  for (const token of userTokens) {
    for (const courseId of courseIds) {
      tasks.push((async () => {
        try {
          const orderId = await createOrder(token, courseId, 9.99);
          await preparePayment(token, orderId);
          successCount++;
        } catch (e) {
          failCount++;
          console.error(e.message);
        }
      })());
    }
  }

  await Promise.all(tasks);
  
  const endTime = Date.now();
  console.log('\n--- Stress Test Completed ---');
  console.log(`Total Purchase Tasks: ${tasks.length}`);
  console.log(`Success: ${successCount}`);
  console.log(`Failed: ${failCount}`);
  console.log(`Time taken: ${endTime - startTime} ms`);
  console.log(`Requests per second: ${((tasks.length * 2) / ((endTime - startTime) / 1000)).toFixed(2)} req/s (2 API calls per task)`);
}

runTest().catch(console.error);