mm_mongodb 1.5.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +392 -261
  2. package/index.js +2839 -3978
  3. package/package.json +4 -4
  4. package/test.js +807 -285
package/test.js CHANGED
@@ -1,296 +1,818 @@
1
+ const assert = require('assert');
1
2
  const MongoDB = require('./index.js').MongoDB;
2
3
  const mongodbAdmin = require('./index.js').mongodbAdmin;
3
4
 
5
+ /**
6
+ * 测试运行器,与 mm_cachebase 测试风格对齐
7
+ */
8
+ class TestRunner {
9
+ constructor() {
10
+ this.totalTests = 0;
11
+ this.passedTests = 0;
12
+ this.results = [];
13
+ }
14
+
15
+ async runTest(name, testFunction) {
16
+ this.totalTests++;
17
+ try {
18
+ await testFunction();
19
+ this.passedTests++;
20
+ this.results.push({ name, passed: true });
21
+ $.log.debug(`✅ ${name}`);
22
+ } catch (error) {
23
+ this.results.push({ name, passed: false, error: error.message });
24
+ $.log.debug(`❌ ${name} - ${error.message}`);
25
+ }
26
+ }
27
+
28
+ displayResults() {
29
+ $.log.debug('\n========== 测试结果 ==========');
30
+ const passRate = (this.passedTests / this.totalTests * 100).toFixed(2);
31
+ $.log.debug(`通过: ${this.passedTests}/${this.totalTests} (${passRate}%)`);
32
+
33
+ // 显示失败的测试
34
+ const failedTests = this.results.filter(r => !r.passed);
35
+ if (failedTests.length > 0) {
36
+ $.log.debug('\n失败的测试:');
37
+ failedTests.forEach(test => {
38
+ $.log.debug(` - ${test.name}: ${test.error}`);
39
+ });
40
+ }
41
+
42
+ return passRate;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * 清理测试数据
48
+ * @param {MongoDB} db 数据库实例
49
+ * @param {Array} keys 要清理的键名数组
50
+ */
51
+ async function cleanupKeys(db, keys) {
52
+ if (keys.length === 0) return;
53
+ try {
54
+ await db.delete({
55
+ key: { $in: keys }
56
+ });
57
+ } catch (error) {
58
+ // 忽略清理错误
59
+ }
60
+ }
61
+
4
62
  async function test() {
5
- try {
6
- var bl, num, arr = [];
7
- // 使用默认配置
8
- var config = {
9
- host: 'localhost',
10
- port: 27017,
11
- user: '',
12
- password: '',
13
- database: 'mm'
14
- };
15
- var rs = mongodbAdmin('sys', config);
16
- await rs.open();
17
- await rs.addTable('cache_test');
18
-
19
- // 清理之前的测试数据
20
- await rs.delete({
21
- key: {
22
- $in: [
23
- "test_key", "test_obj", "temp_key", "counter", "float_counter",
24
- "test_str", "hash_key", "set_key", "zset_key", "sort_key"
25
- ]
26
- }
27
- });
28
-
29
- $.log.debug('[MongoDB] ==============================');
30
- $.log.debug('[MongoDB] 开始兼容性测试 - 核心缓存方法');
31
- $.log.debug('[MongoDB] ==============================');
32
-
33
- // 测试1: set和get操作
34
- $.log.debug('[MongoDB] \n测试1: 设置和获取对象');
35
- await rs.set("test_obj", {
36
- name: "李四",
37
- age: 18
38
- });
39
- var user = await rs.get("test_obj");
40
- $.log.debug('[MongoDB] 测试输出', user);
41
-
42
- // 测试2: 设置和获取基本值
43
- $.log.debug('[MongoDB] \n测试2: 设置和获取基本值');
44
- bl = await rs.set("test_key", "test_value");
45
- $.log.debug('[MongoDB] set结果(true):', bl);
46
-
47
- var value = await rs.get("test_key");
48
- $.log.debug('[MongoDB] get结果(test_value):', value);
49
-
50
- // 测试3: 数值增加相关 (addInt, incr, decr)
51
- $.log.debug('[MongoDB] \n测试3: 数值增加相关');
52
- await rs.set("counter", 10);
53
- var newCount = await rs.addInt("counter", 5);
54
- $.log.debug('[MongoDB] addInt增加后的值(15):', newCount);
55
-
56
- newCount = await rs.incr("counter");
57
- $.log.debug('[MongoDB] incr增加后的值(16):', newCount);
58
-
59
- newCount = await rs.decr("counter");
60
- $.log.debug('[MongoDB] decr减少后的值(15):', newCount);
61
-
62
- // 测试4: 浮点数增加 (addFloat)
63
- $.log.debug('[MongoDB] \n测试4: 浮点数增加');
64
- await rs.set("float_counter", 10.5);
65
- var newFloat = await rs.addFloat("float_counter", 2.3);
66
- $.log.debug('[MongoDB] addFloat增加后的值(12.8):', newFloat);
67
-
68
- // 测试5: 字符串操作 (addStr)
69
- $.log.debug('[MongoDB] \n测试5: 字符串操作');
70
- await rs.set("test_str", "Hello");
71
- var strLen = await rs.addStr("test_str", " World");
72
- $.log.debug('[MongoDB] addStr追加后长度(11):', strLen);
73
- var fullStr = await rs.get("test_str");
74
- $.log.debug('[MongoDB] 完整字符串(Hello World):', fullStr);
75
-
76
- // 测试6: 条件设置 (add - 仅当键不存在时设置)
77
- $.log.debug('[MongoDB] \n测试6: 条件设置');
78
- await rs.set("exists_key", "已存在的值");
79
- var addResult1 = await rs.add("exists_key", "这不会被设置");
80
- var addResult2 = await rs.add("new_key", "新键值");
81
- $.log.debug('[MongoDB] 已有键add结果(false):', addResult1);
82
- $.log.debug('[MongoDB] 新键add结果(true):', addResult2);
83
- $.log.debug('[MongoDB] 新键值:', await rs.get("new_key"));
84
-
85
- // 测试7: 键检查 (has, exists)
86
- $.log.debug('[MongoDB] \n测试7: 键检查');
87
- var hasResult = await rs.has("new_key");
88
- var existsResult = await rs.exists("new_key");
89
- $.log.debug('[MongoDB] has检查结果(true):', hasResult);
90
- $.log.debug('[MongoDB] exists检查结果(1):', existsResult);
91
-
92
- // 测试8: 批量操作 (mset, mget)
93
- $.log.debug('[MongoDB] \n测试8: 批量操作');
94
- bl = await rs.mset({
95
- "batch1": "值1",
96
- "batch2": "值2",
97
- "batch3": {name: "测试对象"}
98
- });
99
- $.log.debug('[MongoDB] mset结果(OK):', bl);
100
-
101
- var batchResult = await rs.mget(["batch1", "batch2", "batch3"]);
102
- $.log.debug('[MongoDB] 批量获取结果:', batchResult);
103
-
104
- // 测试9: 删除操作 (del)
105
- $.log.debug('[MongoDB] \n测试9: 删除操作');
106
- var delResult = await rs.del("batch1");
107
- $.log.debug('[MongoDB] 单键删除结果(true):', delResult);
108
- var delMultiResult = await rs.del(["batch2", "batch3"]);
109
- $.log.debug('[MongoDB] 多键删除结果(true):', delMultiResult);
110
-
111
- $.log.debug('[MongoDB] ==============================');
112
- $.log.debug('[MongoDB] 开始兼容性测试 - 哈希表操作');
113
- $.log.debug('[MongoDB] ==============================');
114
-
115
- // 测试10: 哈希表基本操作 (hset, hget)
116
- $.log.debug('[MongoDB] \n测试10: 哈希表基本操作');
117
- var hset1 = await rs.hset("hash_key", "field1", "value1");
118
- var hset2 = await rs.hset("hash_key", "field2", {name: "测试对象"});
119
- $.log.debug('[MongoDB] hset创建新字段结果(1):', hset1);
120
- $.log.debug('[MongoDB] hset创建新字段结果(1):', hset2);
121
-
122
- var hget1 = await rs.hget("hash_key", "field1");
123
- var hget2 = await rs.hget("hash_key", "field2");
124
- $.log.debug('[MongoDB] hget field1结果(value1):', hget1);
125
- $.log.debug('[MongoDB] hget field2结果:', hget2);
126
-
127
- // 测试11: 更新哈希字段
128
- $.log.debug('[MongoDB] \n测试11: 更新哈希字段');
129
- var hsetUpdate = await rs.hset("hash_key", "field1", "updated_value");
130
- $.log.debug('[MongoDB] hset更新字段结果(0):', hsetUpdate);
131
- $.log.debug('[MongoDB] 更新后hget field1:', await rs.hget("hash_key", "field1"));
132
-
133
- // 测试12: 获取所有哈希字段 (hgetall, hkeys, hvals, hlen)
134
- $.log.debug('[MongoDB] \n测试12: 获取所有哈希字段');
135
- var hgetall = await rs.hgetall("hash_key");
136
- $.log.debug('[MongoDB] hgetall结果:', hgetall);
137
-
138
- var hkeys = await rs.hkeys("hash_key");
139
- $.log.debug('[MongoDB] hkeys结果:', hkeys);
140
-
141
- var hvals = await rs.hvals("hash_key");
142
- $.log.debug('[MongoDB] hvals结果:', hvals);
143
-
144
- var hlen = await rs.hlen("hash_key");
145
- $.log.debug('[MongoDB] hlen结果(2):', hlen);
146
-
147
- // 测试13: 哈希字段检查和删除 (hexists, hdel)
148
- $.log.debug('[MongoDB] \n测试13: 哈希字段检查和删除');
149
- var hexists1 = await rs.hexists("hash_key", "field1");
150
- var hexists2 = await rs.hexists("hash_key", "non_existent");
151
- $.log.debug('[MongoDB] hexists存在字段结果(true):', hexists1);
152
- $.log.debug('[MongoDB] hexists不存在字段结果(false):', hexists2);
153
-
154
- var hdel = await rs.hdel("hash_key", "field1");
155
- $.log.debug('[MongoDB] hdel结果(true):', hdel);
156
- $.log.debug('[MongoDB] 删除后hget field1:', await rs.hget("hash_key", "field1"));
157
-
158
- $.log.debug('[MongoDB] ==============================');
159
- $.log.debug('[MongoDB] 开始兼容性测试 - 集合操作');
160
- $.log.debug('[MongoDB] ==============================');
161
-
162
- // 测试14: 集合基本操作 (saddMulti, sremMulti)
163
- $.log.debug('[MongoDB] \n测试14: 集合基本操作');
164
- var sadd = await rs.saddMulti("set_key", ["member1", "member2", "member3"]);
165
- $.log.debug('[MongoDB] saddMulti结果(3):', sadd);
166
-
167
- var srem = await rs.sremMulti("set_key", ["member2"]);
168
- $.log.debug('[MongoDB] sremMulti结果(1):', srem);
169
-
170
- // 测试15: 集合成员检查 (sismember)
171
- $.log.debug('[MongoDB] \n测试15: 集合成员检查');
172
- var sismember1 = await rs.sismember("set_key", "member1");
173
- var sismember2 = await rs.sismember("set_key", "member2");
174
- $.log.debug('[MongoDB] sismember存在成员结果(true):', sismember1);
175
- $.log.debug('[MongoDB] sismember不存在成员结果(false):', sismember2);
176
-
177
- // 测试16: 获取集合成员 (smembers, scard)
178
- $.log.debug('[MongoDB] \n测试16: 获取集合成员');
179
- var smembers = await rs.smembers("set_key");
180
- var scard = await rs.scard("set_key");
181
- $.log.debug('[MongoDB] smembers结果:', smembers);
182
- $.log.debug('[MongoDB] scard结果(2):', scard);
183
-
184
- // 测试17: 集合操作 (sinter, sunion, sdiff)
185
- $.log.debug('[MongoDB] \n测试17: 集合操作');
186
- await rs.saddMulti("set_key2", ["member2", "member3", "member4"]);
187
- var sinter = await rs.sinter("set_key", "set_key2");
188
- var sunion = await rs.sunion("set_key", "set_key2");
189
- var sdiff = await rs.sdiff("set_key", "set_key2");
190
- $.log.debug('[MongoDB] sinter交集结果:', sinter);
191
- $.log.debug('[MongoDB] sunion并集结果:', sunion);
192
- $.log.debug('[MongoDB] sdiff差集结果:', sdiff);
193
-
194
- $.log.debug('[MongoDB] ==============================');
195
- $.log.debug('[MongoDB] 开始兼容性测试 - 有序集合操作');
196
- $.log.debug('[MongoDB] ==============================');
197
-
198
- // 测试18: 有序集合基本操作 (zadd, zrem)
199
- $.log.debug('[MongoDB] \n测试18: 有序集合基本操作');
200
- var zadd1 = await rs.zadd("zset_key", 10, "zmember1");
201
- var zadd2 = await rs.zadd("zset_key", 5, "zmember2");
202
- $.log.debug('[MongoDB] zadd结果(true):', zadd1);
203
- $.log.debug('[MongoDB] zadd结果(true):', zadd2);
204
-
205
- var zrem = await rs.zrem("zset_key", "zmember2");
206
- $.log.debug('[MongoDB] zrem删除结果(1):', zrem);
207
-
208
- // 测试19: 获取有序集合成员 (zrangebyscore)
209
- $.log.debug('[MongoDB] \n测试19: 获取有序集合成员');
210
- var zrangebyscore = await rs.zrangebyscore("zset_key", 0, 20);
211
- $.log.debug('[MongoDB] zrangebyscore结果:', zrangebyscore);
212
-
213
- // 测试20: 有序集合分数操作 (zscore)
214
- $.log.debug('[MongoDB] \n测试20: 有序集合分数操作');
215
- var zscore = await rs.zscore("zset_key", "zmember1");
216
- $.log.debug('[MongoDB] zscore结果(10):', zscore);
217
-
218
- // 测试21: 有序集合成员数量 (zcard)
219
- $.log.debug('[MongoDB] \n测试21: 有序集合成员数量');
220
- var zcard = await rs.zcard("zset_key");
221
- $.log.debug('[MongoDB] zcard结果(1):', zcard);
222
-
223
- $.log.debug('[MongoDB] ==============================');
224
- $.log.debug('[MongoDB] 开始兼容性测试 - 列表操作');
225
- $.log.debug('[MongoDB] ==============================');
226
-
227
- // 测试22: 列表基本操作 (lpush, rpush)
228
- $.log.debug('[MongoDB] \n测试22: 列表基本操作');
229
- var lpush = await rs.lpush("list_key", "item0");
230
- var rpush1 = await rs.rpush("list_key", "item1");
231
- var rpush2 = await rs.rpush("list_key", "item2");
232
- $.log.debug('[MongoDB] lpush结果(1):', lpush);
233
- $.log.debug('[MongoDB] rpush结果(2):', rpush1);
234
- $.log.debug('[MongoDB] rpush结果(3):', rpush2);
235
-
236
- // 测试23: 列表长度 (llen)
237
- $.log.debug('[MongoDB] \n测试23: 列表长度');
238
- var llen = await rs.llen("list_key");
239
- $.log.debug('[MongoDB] llen结果(3):', llen);
240
-
241
- // 测试24: 列表范围 (lrange)
242
- $.log.debug('[MongoDB] \n测试24: 列表范围');
243
- var lrange = await rs.lrange("list_key", 0, -1);
244
- $.log.debug('[MongoDB] lrange结果:', lrange);
245
-
246
- // 测试25: 列表索引 (lindex)
247
- $.log.debug('[MongoDB] \n测试25: 列表索引');
248
- var lindex = await rs.lindex("list_key", 1);
249
- $.log.debug('[MongoDB] lindex结果(item1):', lindex);
250
-
251
- // 测试26: 列表弹出 (lpop, rpop)
252
- $.log.debug('[MongoDB] \n测试26: 列表弹出');
253
- var lpop = await rs.lpop("list_key");
254
- var rpop = await rs.rpop("list_key");
255
- $.log.debug('[MongoDB] lpop结果(item0):', lpop);
256
- $.log.debug('[MongoDB] rpop结果(item2):', rpop);
257
-
258
- // 清理所有测试数据
259
- $.log.debug('[MongoDB] \n清理所有测试数据...');
260
- await rs.delete({
261
- key: {
262
- $in: [
263
- "test_obj", "test_key", "temp_key", "counter", "float_counter", "test_str",
264
- "exists_key", "new_key", "hash_key", "set_key", "set_key2", "zset_key",
265
- "list_key"
266
- ]
267
- }
268
- });
269
-
270
- // 关闭连接
271
- $.log.debug('[MongoDB] \n关闭连接...');
272
- bl = await rs.close();
273
- $.log.debug('[MongoDB] 关闭连接结果:', bl);
274
-
275
- $.log.debug('[MongoDB] \n==============================');
276
- $.log.debug('[MongoDB] 所有兼容性测试完成!');
277
- $.log.debug('[MongoDB] ==============================');
278
- } catch (error) {
279
- $.log.error('[MongoDB] 测试过程中出现错误:', error);
280
- }
63
+ $.log.debug('[MongoDB] ==============================');
64
+ $.log.debug('[MongoDB] 开始兼容性测试(对齐 mm_redis / mm_cachebase 接口)');
65
+ $.log.debug('[MongoDB] ==============================');
66
+
67
+ try {
68
+ // 使用默认配置创建实例
69
+ const config = {
70
+ host: 'localhost',
71
+ port: 27017,
72
+ user: '',
73
+ password: '',
74
+ database: 'mm'
75
+ };
76
+ const cache = mongodbAdmin('test', config);
77
+ await cache.open();
78
+ // 确保使用测试表,避免污染其他数据
79
+ await cache.addTable('cache_test');
80
+
81
+ const runner = new TestRunner();
82
+ // 用于统一清理的键列表
83
+ const allTestKeys = [];
84
+
85
+ // ==================== 测试基础方法 ====================
86
+ $.log.debug('[MongoDB] \n========== 测试基础方法 ==========');
87
+
88
+ await runner.runTest('set和get方法', async () => {
89
+ await cache.set('test_key', 'test_value');
90
+ allTestKeys.push('test_key');
91
+ const value = await cache.get('test_key');
92
+ assert.equal(value, 'test_value', 'set和get方法测试失败');
93
+
94
+ await cache.del('test_key');
95
+ const deleted_value = await cache.get('test_key');
96
+ assert.equal(deleted_value, null, 'del方法测试失败');
97
+ });
98
+
99
+ await runner.runTest('del方法(返回删除数量)', async () => {
100
+ await cache.set('key2', 'value2');
101
+ allTestKeys.push('key2');
102
+ const deleted = await cache.del('key2');
103
+ // del 返回删除的数量,对齐 mm_cachebase
104
+ if (deleted !== 1) {
105
+ throw new Error(`删除失败,预期: 1, 实际: ${deleted}`);
106
+ }
107
+ const value = await cache.get('key2');
108
+ if (value !== null) {
109
+ throw new Error(`键未被删除,值: ${value}`);
110
+ }
111
+ // 删除不存在的键返回 0
112
+ const deleted2 = await cache.del('not_exist');
113
+ if (deleted2 !== 0) {
114
+ throw new Error(`删除不存在键预期: 0, 实际: ${deleted2}`);
115
+ }
116
+ });
117
+
118
+ await runner.runTest('exists/has方法(返回数字)', async () => {
119
+ await cache.set('key3', 'value3');
120
+ allTestKeys.push('key3');
121
+ const exists = await cache.exists('key3');
122
+ // exists 返回 0/1,对齐 mm_cachebase
123
+ if (exists !== 1) {
124
+ throw new Error(`exists失败,预期: 1, 实际: ${exists}`);
125
+ }
126
+ const has = await cache.has('key3');
127
+ if (!has) {
128
+ throw new Error(`has失败,预期: true, 实际: ${has}`);
129
+ }
130
+ // 不存在的键返回 0
131
+ const exists2 = await cache.exists('not_exist');
132
+ if (exists2 !== 0) {
133
+ throw new Error(`exists不存在键预期: 0, 实际: ${exists2}`);
134
+ }
135
+ });
136
+
137
+ await runner.runTest('keys方法', async () => {
138
+ await cache.set('key4', 'value4');
139
+ await cache.set('key5', 'value5');
140
+ allTestKeys.push('key4', 'key5');
141
+ const keys = await cache.keys('key4*');
142
+ // MongoDB 的 keys 基于 pattern 匹配,仅校验 key4 存在
143
+ if (!keys.includes('key4')) {
144
+ throw new Error(`keys失败,预期包含key4, 实际: ${JSON.stringify(keys)}`);
145
+ }
146
+ });
147
+
148
+ await runner.runTest('dbsize方法', async () => {
149
+ const size = await cache.dbsize();
150
+ if (typeof size !== 'number' || size < 0) {
151
+ throw new Error(`dbsize失败,预期非负数, 实际: ${size}`);
152
+ }
153
+ });
154
+
155
+ await runner.runTest('getset方法', async () => {
156
+ await cache.set('key6', 'value6');
157
+ allTestKeys.push('key6');
158
+ const oldValue = await cache.getset('key6', 'newvalue6');
159
+ if (oldValue !== 'value6') {
160
+ throw new Error(`getset失败,预期旧值: value6, 实际: ${oldValue}`);
161
+ }
162
+ const newValue = await cache.get('key6');
163
+ if (newValue !== 'newvalue6') {
164
+ throw new Error(`getset失败,预期新值: newvalue6, 实际: ${newValue}`);
165
+ }
166
+ });
167
+
168
+ await runner.runTest('flushdb/clear方法(带pattern)', async () => {
169
+ await cache.set('flush_test_key', 'value');
170
+ allTestKeys.push('flush_test_key');
171
+ // 使用 clear(pattern) 清理指定前缀的键,避免清空整个表
172
+ const result = await cache.clear('flush_test_*');
173
+ if (result !== true) {
174
+ throw new Error(`clear失败,预期: true, 实际: ${result}`);
175
+ }
176
+ const value = await cache.get('flush_test_key');
177
+ if (value !== null) {
178
+ throw new Error(`clear后键仍存在: ${value}`);
179
+ }
180
+ });
181
+
182
+ await runner.runTest('open/close/isConnected方法', async () => {
183
+ const connected1 = cache.isConnected();
184
+ if (!connected1) {
185
+ throw new Error(`open后应已连接,实际: ${connected1}`);
186
+ }
187
+ // 这里不真正关闭主连接,仅验证接口存在
188
+ if (typeof cache.isConnected !== 'function') {
189
+ throw new Error('isConnected方法不存在');
190
+ }
191
+ });
192
+
193
+ // ==================== 测试哈希表方法 ====================
194
+ $.log.debug('[MongoDB] \n========== 测试哈希表方法 ==========');
195
+
196
+ await runner.runTest('hset和hget方法(返回Boolean)', async () => {
197
+ // hset 返回 true/false,对齐 mm_cachebase
198
+ const result1 = await cache.hset('hash1', 'field1', 'value1');
199
+ allTestKeys.push('hash1');
200
+ if (result1 !== true) {
201
+ throw new Error(`hset新建失败,预期: true, 实际: ${result1}`);
202
+ }
203
+
204
+ const result2 = await cache.hset('hash1', 'field1', 'value1_updated');
205
+ if (result2 !== true) {
206
+ throw new Error(`hset更新失败,预期: true, 实际: ${result2}`);
207
+ }
208
+
209
+ const value = await cache.hget('hash1', 'field1');
210
+ if (value !== 'value1_updated') {
211
+ throw new Error(`hget失败,预期: value1_updated, 实际: ${value}`);
212
+ }
213
+ // 不存在字段返回 null,对齐 mm_cachebase
214
+ const value2 = await cache.hget('hash1', 'non_existent');
215
+ if (value2 !== null) {
216
+ throw new Error(`hget不存在字段预期: null, 实际: ${value2}`);
217
+ }
218
+ });
219
+
220
+ await runner.runTest('hgetall方法', async () => {
221
+ await cache.hset('hash1', 'field2', 'value2');
222
+ const hash = await cache.hgetall('hash1');
223
+ if (hash.field1 !== 'value1_updated' || hash.field2 !== 'value2') {
224
+ throw new Error(`hgetall失败,实际: ${JSON.stringify(hash)}`);
225
+ }
226
+ });
227
+
228
+ await runner.runTest('hkeys/hvals/hlen方法', async () => {
229
+ const keys = await cache.hkeys('hash1');
230
+ if (keys.length !== 2 || !keys.includes('field1') || !keys.includes('field2')) {
231
+ throw new Error(`hkeys失败,实际: ${JSON.stringify(keys)}`);
232
+ }
233
+ const vals = await cache.hvals('hash1');
234
+ if (vals.length !== 2 || !vals.includes('value1_updated') || !vals.includes('value2')) {
235
+ throw new Error(`hvals失败,实际: ${JSON.stringify(vals)}`);
236
+ }
237
+ const len = await cache.hlen('hash1');
238
+ if (len !== 2) {
239
+ throw new Error(`hlen失败,预期: 2, 实际: ${len}`);
240
+ }
241
+ });
242
+
243
+ await runner.runTest('hexists方法', async () => {
244
+ const result1 = await cache.hexists('hash1', 'field1');
245
+ if (result1 !== true) {
246
+ throw new Error(`hexists存在字段失败,预期: true, 实际: ${result1}`);
247
+ }
248
+ const result2 = await cache.hexists('hash1', 'non_existent');
249
+ if (result2 !== false) {
250
+ throw new Error(`hexists不存在字段失败,预期: false, 实际: ${result2}`);
251
+ }
252
+ });
253
+
254
+ await runner.runTest('hdel方法(返回删除数量)', async () => {
255
+ // hdel 返回删除的字段数量,对齐 mm_cachebase
256
+ const result = await cache.hdel('hash1', 'field1');
257
+ if (result !== 1) {
258
+ throw new Error(`hdel失败,预期: 1, 实际: ${result}`);
259
+ }
260
+ const value = await cache.hget('hash1', 'field1');
261
+ if (value !== null) {
262
+ throw new Error(`hdel后字段未被删除,值: ${value}`);
263
+ }
264
+
265
+ // 删除不存在的字段返回 0
266
+ const result2 = await cache.hdel('hash1', 'non_existent');
267
+ if (result2 !== 0) {
268
+ throw new Error(`hdel不存在字段失败,预期: 0, 实际: ${result2}`);
269
+ }
270
+ });
271
+
272
+ await runner.runTest('hmset/hmget方法', async () => {
273
+ const result = await cache.hmset('hash2', { f1: 'v1', f2: 'v2' });
274
+ allTestKeys.push('hash2');
275
+ if (result !== true) {
276
+ throw new Error(`hmset失败,预期: true, 实际: ${result}`);
277
+ }
278
+ const values = await cache.hmget('hash2', ['f1', 'f2', 'non_existent']);
279
+ if (values[0] !== 'v1' || values[1] !== 'v2' || values[2] !== null) {
280
+ throw new Error(`hmget失败,预期: ["v1","v2",null], 实际: ${JSON.stringify(values)}`);
281
+ }
282
+ });
283
+
284
+ // ==================== 测试批量操作 ====================
285
+ $.log.debug('[MongoDB] \n========== 测试批量操作 ==========');
286
+
287
+ await runner.runTest('mset方法(对象参数)', async () => {
288
+ // mset 接受对象参数,对齐 mm_cachebase
289
+ const result = await cache.mset({ key7: 'value7', key8: 'value8' });
290
+ allTestKeys.push('key7', 'key8');
291
+ if (result !== true) {
292
+ throw new Error(`mset失败,预期: true, 实际: ${result}`);
293
+ }
294
+ const value7 = await cache.get('key7');
295
+ const value8 = await cache.get('key8');
296
+ if (value7 !== 'value7' || value8 !== 'value8') {
297
+ throw new Error(`mset设置失败,value7: ${value7}, value8: ${value8}`);
298
+ }
299
+ });
300
+
301
+ await runner.runTest('mget方法', async () => {
302
+ const values = await cache.mget(['key7', 'key8', 'nonExistentKey']);
303
+ if (values[0] !== 'value7' || values[1] !== 'value8' || values[2] !== null) {
304
+ throw new Error(`mget失败,预期: ["value7","value8",null], 实际: ${JSON.stringify(values)}`);
305
+ }
306
+ });
307
+
308
+ // ==================== 测试过期时间 ====================
309
+ $.log.debug('[MongoDB] \n========== 测试过期时间 ==========');
310
+
311
+ await runner.runTest('set带过期时间', async () => {
312
+ await cache.set('expire1', 'value1', 1); // 1秒过期
313
+ allTestKeys.push('expire1');
314
+ let ttl = await cache.ttl('expire1');
315
+ if (ttl <= 0) {
316
+ throw new Error(`ttl初始值错误: ${ttl}`);
317
+ }
318
+
319
+ // 等待过期
320
+ await new Promise(resolve => setTimeout(resolve, 1100));
321
+
322
+ ttl = await cache.ttl('expire1');
323
+ if (ttl !== -2) {
324
+ throw new Error(`过期后ttl错误,预期: -2, 实际: ${ttl}`);
325
+ }
326
+
327
+ const value = await cache.get('expire1');
328
+ if (value !== null) {
329
+ throw new Error(`过期后键仍存在: ${value}`);
330
+ }
331
+ });
332
+
333
+ await runner.runTest('expire方法', async () => {
334
+ await cache.set('expire2', 'value2');
335
+ allTestKeys.push('expire2');
336
+ const result = await cache.expire('expire2', 1);
337
+ if (result !== true) {
338
+ throw new Error(`expire设置失败,预期: true, 实际: ${result}`);
339
+ }
340
+ let ttl = await cache.ttl('expire2');
341
+ if (ttl <= 0) {
342
+ throw new Error(`expire后ttl错误: ${ttl}`);
343
+ }
344
+ });
345
+
346
+ await runner.runTest('persist方法', async () => {
347
+ await cache.set('expire3', 'value3', 30);
348
+ allTestKeys.push('expire3');
349
+ const result = await cache.persist('expire3');
350
+ if (result !== true) {
351
+ throw new Error(`persist设置失败,预期: true, 实际: ${result}`);
352
+ }
353
+ const ttl = await cache.ttl('expire3');
354
+ if (ttl !== -1) {
355
+ throw new Error(`persist后ttl错误,预期: -1, 实际: ${ttl}`);
356
+ }
357
+ });
358
+
359
+ await runner.runTest('pexpire方法(毫秒过期)', async () => {
360
+ await cache.set('expire4', 'value4');
361
+ allTestKeys.push('expire4');
362
+ const result = await cache.pexpire('expire4', 500); // 500毫秒过期
363
+ if (result !== true) {
364
+ throw new Error(`pexpire设置失败,预期: true, 实际: ${result}`);
365
+ }
366
+ // 等待过期
367
+ await new Promise(resolve => setTimeout(resolve, 600));
368
+ const value = await cache.get('expire4');
369
+ if (value !== null) {
370
+ throw new Error(`pexpire过期后键仍存在: ${value}`);
371
+ }
372
+ });
373
+
374
+ // ==================== 测试数值操作 ====================
375
+ $.log.debug('[MongoDB] \n========== 测试数值操作 ==========');
376
+
377
+ await runner.runTest('incr方法', async () => {
378
+ await cache.del('counter');
379
+ allTestKeys.push('counter');
380
+ const result1 = await cache.incr('counter');
381
+ if (result1 !== 1) {
382
+ throw new Error(`incr初始值失败,预期: 1, 实际: ${result1}`);
383
+ }
384
+ const value1 = await cache.get('counter');
385
+ if (value1 !== 1) {
386
+ throw new Error(`incr值错误,预期: 1, 实际: ${value1}`);
387
+ }
388
+
389
+ const result2 = await cache.incr('counter');
390
+ if (result2 !== 2) {
391
+ throw new Error(`incr递增失败,预期: 2, 实际: ${result2}`);
392
+ }
393
+ });
394
+
395
+ await runner.runTest('decr方法', async () => {
396
+ const result = await cache.decr('counter');
397
+ if (result !== 1) {
398
+ throw new Error(`decr递减失败,预期: 1, 实际: ${result}`);
399
+ }
400
+ });
401
+
402
+ await runner.runTest('incrby方法(带seconds)', async () => {
403
+ // incrby 带 seconds 参数,对齐 mm_cachebase
404
+ const result = await cache.incrby('counter', 5);
405
+ if (result !== 6) {
406
+ throw new Error(`incrby增加失败,预期: 6, 实际: ${result}`);
407
+ }
408
+ // 测试带 TTL 的 incrby
409
+ const result2 = await cache.incrby('counter_ttl', 10, 100);
410
+ allTestKeys.push('counter_ttl');
411
+ if (result2 !== 10) {
412
+ throw new Error(`incrby带TTL失败,预期: 10, 实际: ${result2}`);
413
+ }
414
+ const ttl = await cache.ttl('counter_ttl');
415
+ if (ttl <= 0 || ttl > 100) {
416
+ throw new Error(`incrby带TTL的ttl错误: ${ttl}`);
417
+ }
418
+ });
419
+
420
+ await runner.runTest('decrby方法(带seconds)', async () => {
421
+ const result = await cache.decrby('counter', 2);
422
+ if (result !== 4) {
423
+ throw new Error(`decrby减少失败,预期: 4, 实际: ${result}`);
424
+ }
425
+ });
426
+
427
+ await runner.runTest('incrbyfloat方法', async () => {
428
+ const result = await cache.incrbyfloat('counter', 0.5);
429
+ if (result !== 4.5) {
430
+ throw new Error(`incrbyfloat增加失败,预期: 4.5, 实际: ${result}`);
431
+ }
432
+ });
433
+
434
+ await runner.runTest('add方法(SETNX语义)', async () => {
435
+ await cache.del('counter_add');
436
+ allTestKeys.push('counter_add');
437
+ const result = await cache.add('counter_add', 10);
438
+ if (result !== true) {
439
+ throw new Error(`add增加失败,预期: true, 实际: ${result}`);
440
+ }
441
+ const value = await cache.get('counter_add');
442
+ if (value !== 10) {
443
+ throw new Error(`add增加后值错误,预期: 10, 实际: ${value}`);
444
+ }
445
+
446
+ const result2 = await cache.add('counter_add', 20);
447
+ if (result2 !== false) {
448
+ throw new Error(`add键已存在时失败,预期: false, 实际: ${result2}`);
449
+ }
450
+ });
451
+
452
+ await runner.runTest('addInt方法(兼容)', async () => {
453
+ await cache.del('counter_int');
454
+ allTestKeys.push('counter_int');
455
+ const result = await cache.addInt('counter_int', 5);
456
+ if (result !== 5) {
457
+ throw new Error(`addInt增加失败,预期: 5, 实际: ${result}`);
458
+ }
459
+ const result2 = await cache.addInt('counter_int', 3);
460
+ if (result2 !== 8) {
461
+ throw new Error(`addInt累加失败,预期: 8, 实际: ${result2}`);
462
+ }
463
+ });
464
+
465
+ await runner.runTest('addFloat方法(兼容)', async () => {
466
+ await cache.del('counter_float');
467
+ allTestKeys.push('counter_float');
468
+ const result = await cache.addFloat('counter_float', 1.5);
469
+ if (result !== 1.5) {
470
+ throw new Error(`addFloat增加失败,预期: 1.5, 实际: ${result}`);
471
+ }
472
+ const result2 = await cache.addFloat('counter_float', 2.3);
473
+ if (Math.abs(result2 - 3.8) > 0.0001) {
474
+ throw new Error(`addFloat累加失败,预期: 3.8, 实际: ${result2}`);
475
+ }
476
+ });
477
+
478
+ // ==================== 测试字符串操作 ====================
479
+ $.log.debug('[MongoDB] \n========== 测试字符串操作 ==========');
480
+
481
+ await runner.runTest('append方法', async () => {
482
+ await cache.set('str', 'hello');
483
+ allTestKeys.push('str');
484
+ const result = await cache.append('str', ' world');
485
+ if (result !== 11) {
486
+ throw new Error(`append长度错误,预期: 11, 实际: ${result}`);
487
+ }
488
+ const value = await cache.get('str');
489
+ if (value !== 'hello world') {
490
+ throw new Error(`append值错误,预期: hello world, 实际: ${value}`);
491
+ }
492
+ });
493
+
494
+ await runner.runTest('strlen方法', async () => {
495
+ const result = await cache.strlen('str');
496
+ if (result !== 11) {
497
+ throw new Error(`strlen长度错误,预期: 11, 实际: ${result}`);
498
+ }
499
+ const result2 = await cache.strlen('non_existent');
500
+ if (result2 !== 0) {
501
+ throw new Error(`strlen不存在键错误,预期: 0, 实际: ${result2}`);
502
+ }
503
+ });
504
+
505
+ await runner.runTest('setrange方法(追加字符串)', async () => {
506
+ // setrange 为追加字符串语义,对齐 mm_cachebase
507
+ const result = await cache.setrange('str', '!');
508
+ if (result !== 12) {
509
+ throw new Error(`setrange长度错误,预期: 12, 实际: ${result}`);
510
+ }
511
+ const value = await cache.get('str');
512
+ if (value !== 'hello world!') {
513
+ throw new Error(`setrange值错误,预期: hello world!, 实际: ${value}`);
514
+ }
515
+ });
516
+
517
+ // ==================== 测试集合操作 ====================
518
+ $.log.debug('[MongoDB] \n========== 测试集合操作 ==========');
519
+
520
+ await runner.runTest('sadd/smembers/scard方法', async () => {
521
+ const added = await cache.sadd('set1', ['a', 'b', 'c']);
522
+ allTestKeys.push('set1');
523
+ if (added !== 3) {
524
+ throw new Error(`sadd失败,预期: 3, 实际: ${added}`);
525
+ }
526
+ // 重复添加返回 0
527
+ const added2 = await cache.sadd('set1', ['a', 'd']);
528
+ if (added2 !== 1) {
529
+ throw new Error(`sadd重复失败,预期: 1, 实际: ${added2}`);
530
+ }
531
+ const members = await cache.smembers('set1');
532
+ if (members.length !== 4 || !members.includes('a') || !members.includes('d')) {
533
+ throw new Error(`smembers失败,实际: ${JSON.stringify(members)}`);
534
+ }
535
+ const card = await cache.scard('set1');
536
+ if (card !== 4) {
537
+ throw new Error(`scard失败,预期: 4, 实际: ${card}`);
538
+ }
539
+ });
540
+
541
+ await runner.runTest('sismember方法', async () => {
542
+ const result1 = await cache.sismember('set1', 'a');
543
+ if (result1 !== true) {
544
+ throw new Error(`sismember失败,预期: true, 实际: ${result1}`);
545
+ }
546
+ const result2 = await cache.sismember('set1', 'z');
547
+ if (result2 !== false) {
548
+ throw new Error(`sismember不存在预期: false, 实际: ${result2}`);
549
+ }
550
+ });
551
+
552
+ await runner.runTest('srem方法', async () => {
553
+ const removed = await cache.srem('set1', ['a', 'b']);
554
+ if (removed !== 2) {
555
+ throw new Error(`srem失败,预期: 2, 实际: ${removed}`);
556
+ }
557
+ const card = await cache.scard('set1');
558
+ if (card !== 2) {
559
+ throw new Error(`srem后scard失败,预期: 2, 实际: ${card}`);
560
+ }
561
+ });
562
+
563
+ await runner.runTest('sinter/sunion/sdiff方法', async () => {
564
+ await cache.sadd('setA', ['1', '2', '3']);
565
+ await cache.sadd('setB', ['2', '3', '4']);
566
+ allTestKeys.push('setA', 'setB');
567
+
568
+ const inter = await cache.sinter('setA', 'setB');
569
+ if (inter.length !== 2 || !inter.includes('2') || !inter.includes('3')) {
570
+ throw new Error(`sinter失败,实际: ${JSON.stringify(inter)}`);
571
+ }
572
+
573
+ const union = await cache.sunion('setA', 'setB');
574
+ if (union.length !== 4) {
575
+ throw new Error(`sunion失败,预期长度4, 实际: ${JSON.stringify(union)}`);
576
+ }
577
+
578
+ const diff = await cache.sdiff('setA', 'setB');
579
+ if (diff.length !== 1 || diff[0] !== '1') {
580
+ throw new Error(`sdiff失败,实际: ${JSON.stringify(diff)}`);
581
+ }
582
+ });
583
+
584
+ // ==================== 测试有序集合操作 ====================
585
+ $.log.debug('[MongoDB] \n========== 测试有序集合操作 ==========');
586
+
587
+ await runner.runTest('zadd/zcard/zscore方法', async () => {
588
+ const added1 = await cache.zadd('zset1', 10, 'member1');
589
+ allTestKeys.push('zset1');
590
+ if (added1 !== true) {
591
+ throw new Error(`zadd新成员失败,预期: true, 实际: ${added1}`);
592
+ }
593
+ const added2 = await cache.zadd('zset1', 20, 'member2');
594
+ if (added2 !== true) {
595
+ throw new Error(`zadd新成员2失败,预期: true, 实际: ${added2}`);
596
+ }
597
+ // 更新已有成员返回 false
598
+ const added3 = await cache.zadd('zset1', 15, 'member1');
599
+ if (added3 !== false) {
600
+ throw new Error(`zadd更新成员失败,预期: false, 实际: ${added3}`);
601
+ }
602
+ const card = await cache.zcard('zset1');
603
+ if (card !== 2) {
604
+ throw new Error(`zcard失败,预期: 2, 实际: ${card}`);
605
+ }
606
+ const score = await cache.zscore('zset1', 'member1');
607
+ if (score !== 15) {
608
+ throw new Error(`zscore失败,预期: 15, 实际: ${score}`);
609
+ }
610
+ });
611
+
612
+ await runner.runTest('zrank/zrange方法', async () => {
613
+ const rank1 = await cache.zrank('zset1', 'member1');
614
+ if (rank1 !== 0) {
615
+ throw new Error(`zrank失败,预期: 0, 实际: ${rank1}`);
616
+ }
617
+ const range = await cache.zrange('zset1', 0, -1);
618
+ if (range.length !== 2 || range[0] !== 'member1' || range[1] !== 'member2') {
619
+ throw new Error(`zrange失败,实际: ${JSON.stringify(range)}`);
620
+ }
621
+ const rangeWithScores = await cache.zrange('zset1', 0, -1, true);
622
+ if (rangeWithScores.length !== 2 || rangeWithScores[0].member !== 'member1' || rangeWithScores[0].score !== 15) {
623
+ throw new Error(`zrange带分数失败,实际: ${JSON.stringify(rangeWithScores)}`);
624
+ }
625
+ });
626
+
627
+ await runner.runTest('zincrby/zrem方法', async () => {
628
+ const newScore = await cache.zincrby('zset1', 5, 'member1');
629
+ if (newScore !== 20) {
630
+ throw new Error(`zincrby失败,预期: 20, 实际: ${newScore}`);
631
+ }
632
+ const removed = await cache.zrem('zset1', 'member1');
633
+ if (removed !== 1) {
634
+ throw new Error(`zrem失败,预期: 1, 实际: ${removed}`);
635
+ }
636
+ const card = await cache.zcard('zset1');
637
+ if (card !== 1) {
638
+ throw new Error(`zrem后zcard失败,预期: 1, 实际: ${card}`);
639
+ }
640
+ });
641
+
642
+ // ==================== 测试列表操作 ====================
643
+ $.log.debug('[MongoDB] \n========== 测试列表操作 ==========');
644
+
645
+ await runner.runTest('setForList/addForList/getForList方法', async () => {
646
+ await cache.setForList('list1', ['a', 'b', 'c']);
647
+ allTestKeys.push('list1');
648
+ const len = await cache.addForList('list1', 'd');
649
+ if (len !== 4) {
650
+ throw new Error(`addForList长度错误,预期: 4, 实际: ${len}`);
651
+ }
652
+ const list = await cache.getForList('list1', 0, -1);
653
+ if (list.length !== 4 || list[3] !== 'd') {
654
+ throw new Error(`getForList失败,实际: ${JSON.stringify(list)}`);
655
+ }
656
+ });
657
+
658
+ await runner.runTest('hasForList方法', async () => {
659
+ const result1 = await cache.hasForList('list1', 'a');
660
+ if (result1 !== true) {
661
+ throw new Error(`hasForList存在失败,预期: true, 实际: ${result1}`);
662
+ }
663
+ const result2 = await cache.hasForList('list1', 'z');
664
+ if (result2 !== false) {
665
+ throw new Error(`hasForList不存在失败,预期: false, 实际: ${result2}`);
666
+ }
667
+ });
668
+
669
+ await runner.runTest('clearForList方法', async () => {
670
+ const result = await cache.clearForList('list1');
671
+ if (result !== true) {
672
+ throw new Error(`clearForList失败,预期: true, 实际: ${result}`);
673
+ }
674
+ const list = await cache.getForList('list1', 0, -1);
675
+ if (list.length !== 0) {
676
+ throw new Error(`clearForList后列表不为空,实际: ${JSON.stringify(list)}`);
677
+ }
678
+ });
679
+
680
+ // ==================== 测试发布订阅 ====================
681
+ $.log.debug('[MongoDB] \n========== 测试发布订阅 ==========');
682
+
683
+ await runner.runTest('subscribe/publish方法', async () => {
684
+ let receivedMessage = null;
685
+ await cache.subscribe('channel1', (msg) => {
686
+ receivedMessage = msg;
687
+ });
688
+ const count = await cache.publish('channel1', 'hello');
689
+ if (count !== 1) {
690
+ throw new Error(`publish接收者数量失败,预期: 1, 实际: ${count}`);
691
+ }
692
+ if (receivedMessage !== 'hello') {
693
+ throw new Error(`订阅未收到消息,预期: hello, 实际: ${receivedMessage}`);
694
+ }
695
+ });
696
+
697
+ await runner.runTest('unsubscribe方法', async () => {
698
+ let received = false;
699
+ await cache.subscribe('channel2', () => { received = true; });
700
+ await cache.unsubscribe('channel2');
701
+ const count = await cache.publish('channel2', 'hello');
702
+ if (count !== 0) {
703
+ throw new Error(`unsubscribe后publish预期: 0, 实际: ${count}`);
704
+ }
705
+ if (received) {
706
+ throw new Error(`unsubscribe后仍收到消息`);
707
+ }
708
+ });
709
+
710
+ // ==================== 测试事件触发(冒号风格) ====================
711
+ $.log.debug('[MongoDB] \n========== 测试事件触发(冒号风格) ==========');
712
+
713
+ await runner.runTest('set事件触发(冒号风格)', async () => {
714
+ return new Promise(async (resolve, reject) => {
715
+ let beforeTriggered = false;
716
+ let afterTriggered = false;
717
+
718
+ // 事件名为冒号风格,对齐 mm_cachebase
719
+ cache.once('set:before', (data) => {
720
+ if (data.key === 'event_key' && data.value === 'event_value') {
721
+ beforeTriggered = true;
722
+ }
723
+ });
724
+
725
+ cache.once('set:after', (data) => {
726
+ if (data.key === 'event_key' && data.value === 'event_value' && data.success === true) {
727
+ afterTriggered = true;
728
+ setTimeout(() => {
729
+ if (beforeTriggered && afterTriggered) {
730
+ resolve();
731
+ } else {
732
+ reject(new Error('set事件未全部触发'));
733
+ }
734
+ }, 10);
735
+ }
736
+ });
737
+
738
+ await cache.set('event_key', 'event_value');
739
+ allTestKeys.push('event_key');
740
+ });
741
+ });
742
+
743
+ await runner.runTest('error事件触发(冒号风格)', async () => {
744
+ return new Promise(async (resolve, reject) => {
745
+ // 事件名为冒号风格
746
+ cache.once('mset:error', (data) => {
747
+ if (data.error) {
748
+ resolve();
749
+ } else {
750
+ reject(new Error('mset:error事件触发但数据不正确'));
751
+ }
752
+ });
753
+
754
+ // 传入非法参数触发错误,mset 内部 catch 后返回 false 并触发 mset:error 事件
755
+ const result = await cache.mset(null);
756
+ if (result !== false) {
757
+ reject(new Error(`mset应返回false但返回: ${result}`));
758
+ }
759
+ // 超时保护,若事件未触发则失败
760
+ setTimeout(() => {
761
+ reject(new Error('mset:error事件未触发'));
762
+ }, 100);
763
+ });
764
+ });
765
+
766
+ // ==================== 测试管理功能 ====================
767
+ $.log.debug('[MongoDB] \n========== 测试管理功能 ==========');
768
+
769
+ await runner.runTest('mongodbAdmin创建实例', async () => {
770
+ const cache1 = mongodbAdmin('test', config);
771
+ const cache2 = mongodbAdmin('test', config);
772
+ if (cache1 !== cache2) {
773
+ throw new Error('mongodbAdmin应返回相同实例但没有');
774
+ }
775
+
776
+ const cache3 = mongodbAdmin('another_scope', config);
777
+ if (cache1 === cache3) {
778
+ throw new Error('mongodbAdmin应返回不同作用域的不同实例但没有');
779
+ }
780
+ // 关闭另一个作用域的连接
781
+ await cache3.close();
782
+ });
783
+
784
+ // 显示测试结果
785
+ const passRate = runner.displayResults();
786
+ $.log.debug(`[MongoDB] \n测试完成!通过率: ${passRate}%`);
787
+
788
+ // 清理所有测试数据
789
+ $.log.debug('[MongoDB] \n清理所有测试数据...');
790
+ await cleanupKeys(cache, allTestKeys);
791
+
792
+ // 关闭连接
793
+ $.log.debug('[MongoDB] \n关闭连接...');
794
+ await cache.close();
795
+
796
+ $.log.debug('[MongoDB] \n==============================');
797
+ $.log.debug('[MongoDB] 所有兼容性测试完成!');
798
+ $.log.debug('[MongoDB] ==============================');
799
+
800
+ } catch (error) {
801
+ $.log.error('[MongoDB] 测试过程中出现错误:', error);
802
+ }
281
803
  }
282
804
 
283
805
  test().then(() => {
284
- // 测试成功完成
285
- $.log.debug('[MongoDB] 测试脚本正常退出');
286
- process.exit(0);
806
+ // 测试成功完成
807
+ $.log.debug('[MongoDB] 测试脚本正常退出');
808
+ process.exit(0);
287
809
  }).catch(err => {
288
- $.log.error('[MongoDB] 未捕获的错误:', err);
289
- process.exit(1);
810
+ $.log.error('[MongoDB] 未捕获的错误:', err);
811
+ process.exit(1);
290
812
  });
291
813
 
292
- // 添加超时保护,但让Promise处理正常结束
814
+ // 添加超时保护
293
815
  setTimeout(() => {
294
- $.log.warn('[MongoDB] 测试脚本超时');
295
- process.exit(1);
296
- }, 10000); // 10秒超时
816
+ $.log.warn('[MongoDB] 测试脚本超时');
817
+ process.exit(1);
818
+ }, 30000); // 30秒超时(MongoDB 操作可能较慢)