masterrecord 0.3.6 → 0.3.8

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.
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Test: Static Cache Sharing
3
+ * Verifies the cache is static/shared as designed
4
+ */
5
+
6
+ const QueryCache = require('../Cache/QueryCache');
7
+
8
+ console.log("╔════════════════════════════════════════════════════════════════╗");
9
+ console.log("║ Static Cache Test ║");
10
+ console.log("╚════════════════════════════════════════════════════════════════╝\n");
11
+
12
+ let passed = 0;
13
+ let failed = 0;
14
+
15
+ // Simulate context class with static shared cache
16
+ class SimulatedContext {
17
+ static _sharedQueryCache = null;
18
+
19
+ constructor() {
20
+ // Initialize shared query cache (only once across all instances)
21
+ if (!SimulatedContext._sharedQueryCache) {
22
+ SimulatedContext._sharedQueryCache = new QueryCache({
23
+ ttl: 5 * 60 * 1000,
24
+ maxSize: 1000,
25
+ enabled: true
26
+ });
27
+ }
28
+
29
+ // Reference the shared cache
30
+ this._queryCache = SimulatedContext._sharedQueryCache;
31
+ }
32
+
33
+ getCacheStats() {
34
+ return this._queryCache.getStats();
35
+ }
36
+
37
+ clearQueryCache() {
38
+ this._queryCache.clear();
39
+ }
40
+ }
41
+
42
+ // Test 1: Multiple instances share the same cache
43
+ console.log("📝 Test 1: Multiple instances share same cache");
44
+ console.log("──────────────────────────────────────────────────");
45
+
46
+ try {
47
+ const ctx1 = new SimulatedContext();
48
+ const ctx2 = new SimulatedContext();
49
+
50
+ const areSame = ctx1._queryCache === ctx2._queryCache;
51
+ const isStatic = ctx1._queryCache === SimulatedContext._sharedQueryCache;
52
+
53
+ if(areSame && isStatic) {
54
+ console.log(" ✓ Both instances share the same cache");
55
+ console.log(" ✓ Cache is stored in static property");
56
+ passed++;
57
+ } else {
58
+ console.log(` ✗ Instances have separate caches`);
59
+ failed++;
60
+ }
61
+ } catch(err) {
62
+ console.log(` ✗ Error: ${err.message}`);
63
+ failed++;
64
+ }
65
+
66
+ // Test 2: Cache SET in one instance visible in another
67
+ console.log("\n📝 Test 2: Cache operations are shared");
68
+ console.log("──────────────────────────────────────────────────");
69
+
70
+ try {
71
+ const ctx1 = new SimulatedContext();
72
+ const ctx2 = new SimulatedContext();
73
+
74
+ // Instance 1: Add to cache
75
+ const key = ctx1._queryCache.generateKey('SELECT * FROM users', [], 'users');
76
+ ctx1._queryCache.set(key, [{ id: 1, name: 'Alice' }], 'users');
77
+
78
+ // Instance 2: Should see the same cached data
79
+ const cached = ctx2._queryCache.get(key);
80
+
81
+ if(cached && cached[0].name === 'Alice') {
82
+ console.log(" ✓ Cache data visible across instances");
83
+ console.log(" ✓ Data written by ctx1, read by ctx2");
84
+ passed++;
85
+ } else {
86
+ console.log(` ✗ Cache data not shared`);
87
+ failed++;
88
+ }
89
+ } catch(err) {
90
+ console.log(` ✗ Error: ${err.message}`);
91
+ failed++;
92
+ }
93
+
94
+ // Test 3: Cache invalidation in one instance affects another
95
+ console.log("\n📝 Test 3: Cache invalidation is shared");
96
+ console.log("──────────────────────────────────────────────────");
97
+
98
+ try {
99
+ const ctx1 = new SimulatedContext();
100
+ const ctx2 = new SimulatedContext();
101
+
102
+ // Clear for clean test
103
+ ctx1._queryCache.clear();
104
+
105
+ // Instance 1: Add entries
106
+ const key1 = ctx1._queryCache.generateKey('query1', [], 'users');
107
+ const key2 = ctx1._queryCache.generateKey('query2', [], 'users');
108
+ ctx1._queryCache.set(key1, { id: 1 }, 'users');
109
+ ctx1._queryCache.set(key2, { id: 2 }, 'users');
110
+
111
+ // Verify both cached
112
+ const before1 = ctx1._queryCache.get(key1);
113
+ const before2 = ctx2._queryCache.get(key2);
114
+
115
+ // Instance 2: Invalidate
116
+ ctx2._queryCache.invalidateTable('users');
117
+
118
+ // Both instances should see empty cache
119
+ const after1 = ctx1._queryCache.get(key1);
120
+ const after2 = ctx2._queryCache.get(key2);
121
+
122
+ if(before1 !== null && before2 !== null && after1 === null && after2 === null) {
123
+ console.log(" ✓ Invalidation in ctx2 affected ctx1");
124
+ console.log(" ✓ Cache properly shared");
125
+ passed++;
126
+ } else {
127
+ console.log(` ✗ Invalidation not shared`);
128
+ failed++;
129
+ }
130
+ } catch(err) {
131
+ console.log(` ✗ Error: ${err.message}`);
132
+ failed++;
133
+ }
134
+
135
+ // Test 4: Statistics are shared
136
+ console.log("\n📝 Test 4: Statistics are shared");
137
+ console.log("──────────────────────────────────────────────────");
138
+
139
+ try {
140
+ const ctx1 = new SimulatedContext();
141
+ const ctx2 = new SimulatedContext();
142
+
143
+ // Clear for clean test
144
+ ctx1.clearQueryCache();
145
+
146
+ // Instance 1: Generate activity
147
+ const key = ctx1._queryCache.generateKey('test', [], 'users');
148
+ ctx1._queryCache.set(key, 'data', 'users');
149
+ ctx1._queryCache.get(key); // Hit
150
+ ctx1._queryCache.get('nonexistent'); // Miss
151
+
152
+ // Both instances should see same stats
153
+ const stats1 = ctx1.getCacheStats();
154
+ const stats2 = ctx2.getCacheStats();
155
+
156
+ if(stats1.hits === 1 && stats2.hits === 1 && stats1.misses === 1 && stats2.misses === 1) {
157
+ console.log(" ✓ Statistics shared across instances");
158
+ console.log(` ✓ Both see: ${stats1.hits} hit, ${stats1.misses} miss`);
159
+ passed++;
160
+ } else {
161
+ console.log(` ✗ Statistics not shared`);
162
+ failed++;
163
+ }
164
+ } catch(err) {
165
+ console.log(` ✗ Error: ${err.message}`);
166
+ failed++;
167
+ }
168
+
169
+ // Summary
170
+ console.log("\n╔════════════════════════════════════════════════════════════════╗");
171
+ console.log("║ Test Summary ║");
172
+ console.log("╚════════════════════════════════════════════════════════════════╝");
173
+ console.log(`\n ✓ Passed: ${passed}`);
174
+ console.log(` ✗ Failed: ${failed}`);
175
+ console.log(` 📊 Total: ${passed + failed}\n`);
176
+
177
+ if(failed === 0) {
178
+ console.log(" 🎉 All tests passed!\n");
179
+ console.log(" ✅ Static cache pattern verified");
180
+ console.log(" ✅ BUG FIX CONFIRMED: Multi-context cache sharing works!\n");
181
+ process.exit(0);
182
+ } else {
183
+ console.log(" ❌ Some tests failed\n");
184
+ process.exit(1);
185
+ }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Test: Opt-In Caching Behavior
3
+ *
4
+ * Verifies that caching is disabled by default and only enabled with .cache()
5
+ */
6
+
7
+ const QueryCache = require('../Cache/QueryCache');
8
+
9
+ console.log("╔════════════════════════════════════════════════════════════════╗");
10
+ console.log("║ Opt-In Caching Test ║");
11
+ console.log("╚════════════════════════════════════════════════════════════════╝\n");
12
+
13
+ let passed = 0;
14
+ let failed = 0;
15
+
16
+ // Simulate queryMethods with opt-in caching
17
+ class SimulatedQuery {
18
+ constructor(context) {
19
+ this._context = context;
20
+ this.__useCache = false; // Default: caching disabled
21
+ this._queryString = 'SELECT * FROM test';
22
+ this._tableName = 'Test';
23
+ }
24
+
25
+ // Enable caching for this query
26
+ cache() {
27
+ this.__useCache = true;
28
+ return this;
29
+ }
30
+
31
+ // Execute query
32
+ toList() {
33
+ const cacheKey = this._context.cache.generateKey(this._queryString, [], this._tableName);
34
+
35
+ // Check cache if enabled
36
+ if (this.__useCache) {
37
+ const cached = this._context.cache.get(cacheKey);
38
+ if (cached) {
39
+ return cached;
40
+ }
41
+ }
42
+
43
+ // Simulate DB query
44
+ const result = [{ id: 1, name: 'Test' }];
45
+
46
+ // Store in cache if enabled
47
+ if (this.__useCache) {
48
+ this._context.cache.set(cacheKey, result, this._tableName);
49
+ }
50
+
51
+ return result;
52
+ }
53
+ }
54
+
55
+ class SimulatedContext {
56
+ constructor() {
57
+ this.cache = new QueryCache({ ttl: 60000, maxSize: 100 });
58
+ }
59
+
60
+ createQuery() {
61
+ return new SimulatedQuery(this);
62
+ }
63
+ }
64
+
65
+ // Test 1: Default behavior - no caching
66
+ console.log("📝 Test 1: Queries without .cache() are NOT cached");
67
+ console.log("──────────────────────────────────────────────────");
68
+
69
+ try {
70
+ const ctx = new SimulatedContext();
71
+ ctx.cache.clear();
72
+
73
+ // Execute same query twice WITHOUT .cache()
74
+ const result1 = ctx.createQuery().toList();
75
+ const result2 = ctx.createQuery().toList();
76
+
77
+ const stats = ctx.cache.getStats();
78
+
79
+ if(stats.size === 0 && stats.hits === 0) {
80
+ console.log(" ✓ Queries without .cache() do not store results");
81
+ console.log(" ✓ No cache hits recorded");
82
+ console.log(" ✓ Cache size remains 0");
83
+ passed++;
84
+ } else {
85
+ console.log(` ✗ Queries were cached without .cache() call`);
86
+ console.log(` ✗ Cache size: ${stats.size}, hits: ${stats.hits}`);
87
+ failed++;
88
+ }
89
+ } catch(err) {
90
+ console.log(` ✗ Error: ${err.message}`);
91
+ failed++;
92
+ }
93
+
94
+ // Test 2: Opt-in with .cache() enables caching
95
+ console.log("\n📝 Test 2: Queries with .cache() ARE cached");
96
+ console.log("──────────────────────────────────────────────────");
97
+
98
+ try {
99
+ const ctx = new SimulatedContext();
100
+ ctx.cache.clear();
101
+
102
+ // Execute same query twice WITH .cache()
103
+ const result1 = ctx.createQuery().cache().toList();
104
+ const result2 = ctx.createQuery().cache().toList();
105
+
106
+ const stats = ctx.cache.getStats();
107
+
108
+ if(stats.size === 1 && stats.hits === 1 && stats.misses === 1) {
109
+ console.log(" ✓ First query with .cache() stored result (miss)");
110
+ console.log(" ✓ Second query with .cache() hit cache (hit)");
111
+ console.log(` ✓ Cache stats: ${stats.hits} hit, ${stats.misses} miss`);
112
+ passed++;
113
+ } else {
114
+ console.log(` ✗ Caching with .cache() didn't work properly`);
115
+ console.log(` ✗ Expected: 1 hit, 1 miss. Got: ${stats.hits} hits, ${stats.misses} misses`);
116
+ failed++;
117
+ }
118
+ } catch(err) {
119
+ console.log(` ✗ Error: ${err.message}`);
120
+ failed++;
121
+ }
122
+
123
+ // Test 3: Mixed queries - cached and non-cached
124
+ console.log("\n📝 Test 3: Mixed cached and non-cached queries");
125
+ console.log("──────────────────────────────────────────────────");
126
+
127
+ try {
128
+ const ctx = new SimulatedContext();
129
+ ctx.cache.clear();
130
+
131
+ // Non-cached query (no .cache())
132
+ ctx.createQuery().toList();
133
+ ctx.createQuery().toList();
134
+
135
+ // Cached query (with .cache())
136
+ ctx.createQuery().cache().toList();
137
+ ctx.createQuery().cache().toList();
138
+
139
+ const stats = ctx.cache.getStats();
140
+
141
+ if(stats.size === 1 && stats.hits === 1 && stats.misses === 1) {
142
+ console.log(" ✓ Non-cached queries didn't affect cache");
143
+ console.log(" ✓ Cached queries stored and retrieved correctly");
144
+ console.log(` ✓ Cache contains only .cache() queries: ${stats.size} entry`);
145
+ passed++;
146
+ } else {
147
+ console.log(` ✗ Mixed query handling incorrect`);
148
+ console.log(` ✗ Cache size: ${stats.size}, expected: 1`);
149
+ failed++;
150
+ }
151
+ } catch(err) {
152
+ console.log(` ✗ Error: ${err.message}`);
153
+ failed++;
154
+ }
155
+
156
+ // Test 4: Default __useCache flag is false
157
+ console.log("\n📝 Test 4: Default __useCache flag is false");
158
+ console.log("──────────────────────────────────────────────────");
159
+
160
+ try {
161
+ const ctx = new SimulatedContext();
162
+ const query = ctx.createQuery();
163
+
164
+ if(query.__useCache === false) {
165
+ console.log(" ✓ Default __useCache is false");
166
+ console.log(" ✓ Caching is opt-in by default");
167
+ passed++;
168
+ } else {
169
+ console.log(` ✗ Default __useCache is ${query.__useCache}, expected false`);
170
+ failed++;
171
+ }
172
+ } catch(err) {
173
+ console.log(` ✗ Error: ${err.message}`);
174
+ failed++;
175
+ }
176
+
177
+ // Test 5: .cache() sets __useCache to true
178
+ console.log("\n📝 Test 5: .cache() enables caching flag");
179
+ console.log("──────────────────────────────────────────────────");
180
+
181
+ try {
182
+ const ctx = new SimulatedContext();
183
+ const query = ctx.createQuery();
184
+
185
+ const beforeCache = query.__useCache;
186
+ query.cache();
187
+ const afterCache = query.__useCache;
188
+
189
+ if(beforeCache === false && afterCache === true) {
190
+ console.log(" ✓ __useCache starts as false");
191
+ console.log(" ✓ .cache() sets __useCache to true");
192
+ console.log(" ✓ Caching is explicitly enabled");
193
+ passed++;
194
+ } else {
195
+ console.log(` ✗ Flag transition incorrect`);
196
+ console.log(` ✗ Before: ${beforeCache}, After: ${afterCache}`);
197
+ failed++;
198
+ }
199
+ } catch(err) {
200
+ console.log(` ✗ Error: ${err.message}`);
201
+ failed++;
202
+ }
203
+
204
+ // Summary
205
+ console.log("\n╔════════════════════════════════════════════════════════════════╗");
206
+ console.log("║ Test Summary ║");
207
+ console.log("╚════════════════════════════════════════════════════════════════╝");
208
+ console.log(`\n ✓ Passed: ${passed}`);
209
+ console.log(` ✗ Failed: ${failed}`);
210
+ console.log(` 📊 Total: ${passed + failed}\n`);
211
+
212
+ if(failed === 0) {
213
+ console.log(" 🎉 All tests passed!\n");
214
+ console.log(" ✅ Opt-in caching behavior verified");
215
+ console.log(" ✅ Default is safe (no caching)");
216
+ console.log(" ✅ .cache() explicitly enables caching\n");
217
+ process.exit(0);
218
+ } else {
219
+ console.log(" ❌ Some tests failed\n");
220
+ process.exit(1);
221
+ }