@onlineapps/conn-base-cache 1.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.
- package/API.md +692 -0
- package/README.md +383 -0
- package/coverage/clover.xml +205 -0
- package/coverage/coverage-final.json +2 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +116 -0
- package/coverage/lcov-report/index.js.html +2851 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +370 -0
- package/package.json +36 -0
- package/src/index.js +923 -0
- package/test/component/cache.component.test.js +428 -0
- package/test/integration/cache.integration.test.js +356 -0
- package/test/unit/CacheConnector.edge.test.js +532 -0
- package/test/unit/CacheConnector.test.js +811 -0
package/README.md
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
# @onlineapps/conn-base-cache
|
|
2
|
+
|
|
3
|
+
Redis cache connector with TTL, invalidation, and namespace support for OA Drive microservices.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ๐ **Automatic key prefixing** - All keys use `cache:` prefix
|
|
8
|
+
- โฑ๏ธ **TTL support** - Automatic expiration for cached data
|
|
9
|
+
- ๐๏ธ **Namespace isolation** - Separate cache spaces per service
|
|
10
|
+
- ๐ **Built-in statistics** - Hit rate, miss tracking
|
|
11
|
+
- ๐ **Atomic operations** - Increment, decrement support
|
|
12
|
+
- ๐ฏ **Pattern invalidation** - Delete by wildcard patterns
|
|
13
|
+
- ๐ **Safe namespacing** - Never touches `obs:` monitoring keys
|
|
14
|
+
- ๐งช **Mock implementation** - For testing
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @onlineapps/conn-base-cache
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
const CacheConnector = require('@onlineapps/conn-base-cache');
|
|
26
|
+
|
|
27
|
+
const cache = new CacheConnector({
|
|
28
|
+
host: 'localhost',
|
|
29
|
+
port: 6379,
|
|
30
|
+
defaultTTL: 3600, // 1 hour
|
|
31
|
+
namespace: 'invoice-service'
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
await cache.connect();
|
|
35
|
+
|
|
36
|
+
// Set value with TTL
|
|
37
|
+
await cache.set('user:123', { name: 'John', role: 'admin' }, 600); // 10 min
|
|
38
|
+
|
|
39
|
+
// Get value
|
|
40
|
+
const user = await cache.get('user:123');
|
|
41
|
+
|
|
42
|
+
// Delete by pattern
|
|
43
|
+
await cache.deleteByPattern('user:*');
|
|
44
|
+
|
|
45
|
+
// Get statistics
|
|
46
|
+
console.log(cache.getStats());
|
|
47
|
+
// { hits: 1, misses: 0, sets: 1, deletes: 5, errors: 0, hitRate: '100%' }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Configuration
|
|
51
|
+
|
|
52
|
+
| Option | Environment Variable | Default | Description |
|
|
53
|
+
|--------|---------------------|---------|-------------|
|
|
54
|
+
| `host` | `REDIS_HOST` | `localhost` | Redis server host |
|
|
55
|
+
| `port` | `REDIS_PORT` | `6379` | Redis server port |
|
|
56
|
+
| `password` | `REDIS_PASSWORD` | - | Redis password |
|
|
57
|
+
| `db` | `REDIS_DB` | `0` | Redis database number |
|
|
58
|
+
| `defaultTTL` | - | `3600` | Default TTL in seconds |
|
|
59
|
+
| `namespace` | - | - | Key namespace |
|
|
60
|
+
| `maxRetries` | - | `3` | Max connection retries |
|
|
61
|
+
| `retryDelay` | - | `100` | Retry delay in ms |
|
|
62
|
+
|
|
63
|
+
## API Reference
|
|
64
|
+
|
|
65
|
+
### Connection Management
|
|
66
|
+
|
|
67
|
+
#### `connect()`
|
|
68
|
+
Establish Redis connection.
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
await cache.connect();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### `disconnect()`
|
|
75
|
+
Close Redis connection.
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
await cache.disconnect();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Basic Operations
|
|
82
|
+
|
|
83
|
+
#### `get(key)`
|
|
84
|
+
Get value from cache.
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
const value = await cache.get('key');
|
|
88
|
+
// Returns parsed object or string
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### `set(key, value, ttl?)`
|
|
92
|
+
Set value in cache with optional TTL.
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
await cache.set('key', { data: 'value' }, 3600);
|
|
96
|
+
// Returns true on success
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### `delete(key)`
|
|
100
|
+
Delete single key.
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
await cache.delete('key');
|
|
104
|
+
// Returns true if key existed
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### `exists(key)`
|
|
108
|
+
Check if key exists.
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
const exists = await cache.exists('key');
|
|
112
|
+
// Returns boolean
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Pattern Operations
|
|
116
|
+
|
|
117
|
+
#### `deleteByPattern(pattern)`
|
|
118
|
+
Delete all keys matching pattern.
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
const deleted = await cache.deleteByPattern('session:*');
|
|
122
|
+
// Returns number of deleted keys
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### TTL Management
|
|
126
|
+
|
|
127
|
+
#### `ttl(key)`
|
|
128
|
+
Get remaining TTL for key.
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
const seconds = await cache.ttl('key');
|
|
132
|
+
// Returns: seconds (-1 if no TTL, -2 if not exists)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### `expire(key, ttl)`
|
|
136
|
+
Update TTL for existing key.
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
await cache.expire('key', 7200); // 2 hours
|
|
140
|
+
// Returns true on success
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Atomic Operations
|
|
144
|
+
|
|
145
|
+
#### `incr(key, increment?)`
|
|
146
|
+
Increment numeric value.
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const newValue = await cache.incr('counter', 5);
|
|
150
|
+
// Returns new value
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### `decr(key, decrement?)`
|
|
154
|
+
Decrement numeric value.
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const newValue = await cache.decr('counter', 1);
|
|
158
|
+
// Returns new value
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Batch Operations
|
|
162
|
+
|
|
163
|
+
#### `mget(keys)`
|
|
164
|
+
Get multiple values at once.
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
const values = await cache.mget(['key1', 'key2', 'key3']);
|
|
168
|
+
// Returns: { key1: value1, key2: value2, key3: value3 }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### `mset(keyValues, ttl?)`
|
|
172
|
+
Set multiple values at once.
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
await cache.mset({
|
|
176
|
+
'key1': 'value1',
|
|
177
|
+
'key2': { data: 'value2' }
|
|
178
|
+
}, 3600);
|
|
179
|
+
// Returns true on success
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Utility Methods
|
|
183
|
+
|
|
184
|
+
#### `withNamespace(namespace)`
|
|
185
|
+
Create namespaced instance.
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
const userCache = cache.withNamespace('users');
|
|
189
|
+
await userCache.set('123', userData);
|
|
190
|
+
// Actual key: cache:invoice-service:users:123
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
#### `wrap(fn, options)`
|
|
194
|
+
Create cached function (memoization).
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
const cachedFetch = cache.wrap(async (userId) => {
|
|
198
|
+
return await fetchUserFromDB(userId);
|
|
199
|
+
}, {
|
|
200
|
+
ttl: 600,
|
|
201
|
+
keyPrefix: 'user'
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const user = await cachedFetch(123);
|
|
205
|
+
// First call fetches from DB and caches
|
|
206
|
+
// Subsequent calls return from cache
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### `flush(confirm)`
|
|
210
|
+
Clear all cache keys (dangerous!).
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
await cache.flush(true); // Must confirm with true
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### `getStats()`
|
|
217
|
+
Get cache statistics.
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
const stats = cache.getStats();
|
|
221
|
+
// { hits: 50, misses: 10, sets: 30, deletes: 5, errors: 0, hitRate: '83.33%' }
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### `healthCheck()`
|
|
225
|
+
Check Redis connection health.
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
const healthy = await cache.healthCheck();
|
|
229
|
+
// Returns boolean
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Usage Patterns
|
|
233
|
+
|
|
234
|
+
### Service-Level Caching
|
|
235
|
+
|
|
236
|
+
```javascript
|
|
237
|
+
class InvoiceService {
|
|
238
|
+
constructor() {
|
|
239
|
+
this.cache = new CacheConnector({
|
|
240
|
+
namespace: 'invoice-service'
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async getInvoice(id) {
|
|
245
|
+
// Check cache first
|
|
246
|
+
const cached = await this.cache.get(`invoice:${id}`);
|
|
247
|
+
if (cached) return cached;
|
|
248
|
+
|
|
249
|
+
// Fetch from database
|
|
250
|
+
const invoice = await db.getInvoice(id);
|
|
251
|
+
|
|
252
|
+
// Cache for 1 hour
|
|
253
|
+
await this.cache.set(`invoice:${id}`, invoice, 3600);
|
|
254
|
+
|
|
255
|
+
return invoice;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async invalidateInvoice(id) {
|
|
259
|
+
await this.cache.delete(`invoice:${id}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### API Response Caching
|
|
265
|
+
|
|
266
|
+
```javascript
|
|
267
|
+
// In service wrapper
|
|
268
|
+
async function callApiWithCache(operation, params) {
|
|
269
|
+
const cacheKey = `api:${operation}:${JSON.stringify(params)}`;
|
|
270
|
+
|
|
271
|
+
// Try cache
|
|
272
|
+
const cached = await cache.get(cacheKey);
|
|
273
|
+
if (cached) {
|
|
274
|
+
logger.debug('Cache hit for API call');
|
|
275
|
+
return cached;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Make API call
|
|
279
|
+
const result = await apiCaller.call(operation, params);
|
|
280
|
+
|
|
281
|
+
// Cache result
|
|
282
|
+
await cache.set(cacheKey, result, 300); // 5 minutes
|
|
283
|
+
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Session Management
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
const sessionCache = cache.withNamespace('sessions');
|
|
292
|
+
|
|
293
|
+
// Store session
|
|
294
|
+
await sessionCache.set(sessionId, {
|
|
295
|
+
userId: 123,
|
|
296
|
+
roles: ['admin'],
|
|
297
|
+
createdAt: Date.now()
|
|
298
|
+
}, 1800); // 30 minutes
|
|
299
|
+
|
|
300
|
+
// Refresh session TTL
|
|
301
|
+
await sessionCache.expire(sessionId, 1800);
|
|
302
|
+
|
|
303
|
+
// Clear all sessions for user
|
|
304
|
+
await sessionCache.deleteByPattern(`*:user:123`);
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Testing
|
|
308
|
+
|
|
309
|
+
Use the built-in mock for testing:
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
const { MockCacheConnector } = require('@onlineapps/conn-base-cache');
|
|
313
|
+
|
|
314
|
+
describe('MyService', () => {
|
|
315
|
+
let cache;
|
|
316
|
+
|
|
317
|
+
beforeEach(() => {
|
|
318
|
+
cache = new MockCacheConnector();
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('should cache results', async () => {
|
|
322
|
+
await cache.set('test', 'value');
|
|
323
|
+
const value = await cache.get('test');
|
|
324
|
+
expect(value).toBe('value');
|
|
325
|
+
expect(cache.getStats().hits).toBe(1);
|
|
326
|
+
});
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Important Notes
|
|
331
|
+
|
|
332
|
+
1. **Key Prefixing**: All keys automatically get `cache:` prefix
|
|
333
|
+
2. **Namespace Isolation**: Use namespaces to avoid key collisions
|
|
334
|
+
3. **TTL Best Practices**: Always set appropriate TTL to prevent memory issues
|
|
335
|
+
4. **Pattern Deletion**: Use carefully as it can be expensive on large datasets
|
|
336
|
+
5. **Never Access**: This connector never touches `obs:` namespace (monitoring)
|
|
337
|
+
|
|
338
|
+
## Integration with Service Wrapper
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
class ServiceWrapper {
|
|
342
|
+
constructor(config) {
|
|
343
|
+
this.cache = new CacheConnector({
|
|
344
|
+
namespace: config.serviceName
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async processWorkflow(message) {
|
|
349
|
+
// Cache workflow state
|
|
350
|
+
await this.cache.set(
|
|
351
|
+
`workflow:${message.workflowId}`,
|
|
352
|
+
message,
|
|
353
|
+
600 // 10 minutes
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Error Handling
|
|
360
|
+
|
|
361
|
+
All methods throw errors with descriptive messages:
|
|
362
|
+
|
|
363
|
+
```javascript
|
|
364
|
+
try {
|
|
365
|
+
await cache.get('key');
|
|
366
|
+
} catch (error) {
|
|
367
|
+
if (error.message.includes('Cache get failed')) {
|
|
368
|
+
// Handle cache failure
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Performance Tips
|
|
374
|
+
|
|
375
|
+
1. **Use mget/mset** for batch operations
|
|
376
|
+
2. **Enable pipelining** for multiple operations
|
|
377
|
+
3. **Set appropriate TTL** to balance freshness and performance
|
|
378
|
+
4. **Use namespaces** to organize keys
|
|
379
|
+
5. **Monitor hit rate** with getStats()
|
|
380
|
+
|
|
381
|
+
## License
|
|
382
|
+
|
|
383
|
+
MIT
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<coverage generated="1758821391698" clover="3.2.0">
|
|
3
|
+
<project timestamp="1758821391699" name="All files">
|
|
4
|
+
<metrics statements="196" coveredstatements="164" conditionals="81" coveredconditionals="69" methods="42" coveredmethods="28" elements="319" coveredelements="261" complexity="0" loc="196" ncloc="196" packages="1" files="1" classes="1"/>
|
|
5
|
+
<file name="index.js" path="/var/www/html/oa_drive/shared/connector/conn-base-cache/src/index.js">
|
|
6
|
+
<metrics statements="196" coveredstatements="164" conditionals="81" coveredconditionals="69" methods="42" coveredmethods="28"/>
|
|
7
|
+
<line num="16" count="2" type="stmt"/>
|
|
8
|
+
<line num="17" count="2" type="stmt"/>
|
|
9
|
+
<line num="72" count="79" type="stmt"/>
|
|
10
|
+
<line num="86" count="79" type="cond" truecount="2" falsecount="0"/>
|
|
11
|
+
<line num="89" count="79" type="stmt"/>
|
|
12
|
+
<line num="92" count="79" type="stmt"/>
|
|
13
|
+
<line num="93" count="79" type="stmt"/>
|
|
14
|
+
<line num="96" count="79" type="stmt"/>
|
|
15
|
+
<line num="138" count="54" type="cond" truecount="4" falsecount="0"/>
|
|
16
|
+
<line num="139" count="1" type="stmt"/>
|
|
17
|
+
<line num="142" count="53" type="stmt"/>
|
|
18
|
+
<line num="144" count="53" type="stmt"/>
|
|
19
|
+
<line num="145" count="53" type="stmt"/>
|
|
20
|
+
<line num="152" count="0" type="cond" truecount="0" falsecount="2"/>
|
|
21
|
+
<line num="153" count="0" type="stmt"/>
|
|
22
|
+
<line num="155" count="0" type="stmt"/>
|
|
23
|
+
<line num="162" count="53" type="stmt"/>
|
|
24
|
+
<line num="163" count="0" type="stmt"/>
|
|
25
|
+
<line num="164" count="0" type="stmt"/>
|
|
26
|
+
<line num="165" count="0" type="stmt"/>
|
|
27
|
+
<line num="168" count="53" type="stmt"/>
|
|
28
|
+
<line num="169" count="0" type="stmt"/>
|
|
29
|
+
<line num="170" count="0" type="stmt"/>
|
|
30
|
+
<line num="173" count="53" type="stmt"/>
|
|
31
|
+
<line num="174" count="0" type="stmt"/>
|
|
32
|
+
<line num="175" count="0" type="stmt"/>
|
|
33
|
+
<line num="179" count="53" type="cond" truecount="1" falsecount="1"/>
|
|
34
|
+
<line num="180" count="53" type="stmt"/>
|
|
35
|
+
<line num="183" count="52" type="stmt"/>
|
|
36
|
+
<line num="184" count="52" type="stmt"/>
|
|
37
|
+
<line num="186" count="52" type="stmt"/>
|
|
38
|
+
<line num="188" count="1" type="stmt"/>
|
|
39
|
+
<line num="189" count="1" type="stmt"/>
|
|
40
|
+
<line num="205" count="15" type="cond" truecount="2" falsecount="0"/>
|
|
41
|
+
<line num="206" count="14" type="stmt"/>
|
|
42
|
+
<line num="207" count="14" type="stmt"/>
|
|
43
|
+
<line num="208" count="14" type="stmt"/>
|
|
44
|
+
<line num="217" count="98" type="cond" truecount="2" falsecount="0"/>
|
|
45
|
+
<line num="218" count="97" type="stmt"/>
|
|
46
|
+
<line num="220" count="1" type="stmt"/>
|
|
47
|
+
<line num="250" count="31" type="stmt"/>
|
|
48
|
+
<line num="251" count="31" type="stmt"/>
|
|
49
|
+
<line num="252" count="31" type="stmt"/>
|
|
50
|
+
<line num="254" count="29" type="cond" truecount="2" falsecount="0"/>
|
|
51
|
+
<line num="255" count="9" type="stmt"/>
|
|
52
|
+
<line num="256" count="9" type="stmt"/>
|
|
53
|
+
<line num="259" count="20" type="stmt"/>
|
|
54
|
+
<line num="262" count="20" type="stmt"/>
|
|
55
|
+
<line num="263" count="20" type="stmt"/>
|
|
56
|
+
<line num="266" count="11" type="stmt"/>
|
|
57
|
+
<line num="269" count="2" type="stmt"/>
|
|
58
|
+
<line num="270" count="2" type="stmt"/>
|
|
59
|
+
<line num="296" count="29" type="stmt"/>
|
|
60
|
+
<line num="297" count="29" type="stmt"/>
|
|
61
|
+
<line num="298" count="29" type="cond" truecount="2" falsecount="0"/>
|
|
62
|
+
<line num="299" count="28" type="cond" truecount="2" falsecount="0"/>
|
|
63
|
+
<line num="301" count="28" type="cond" truecount="1" falsecount="1"/>
|
|
64
|
+
<line num="302" count="28" type="stmt"/>
|
|
65
|
+
<line num="304" count="0" type="stmt"/>
|
|
66
|
+
<line num="307" count="26" type="stmt"/>
|
|
67
|
+
<line num="308" count="26" type="stmt"/>
|
|
68
|
+
<line num="310" count="3" type="stmt"/>
|
|
69
|
+
<line num="311" count="3" type="stmt"/>
|
|
70
|
+
<line num="332" count="8" type="stmt"/>
|
|
71
|
+
<line num="333" count="8" type="stmt"/>
|
|
72
|
+
<line num="334" count="8" type="stmt"/>
|
|
73
|
+
<line num="336" count="7" type="stmt"/>
|
|
74
|
+
<line num="337" count="7" type="stmt"/>
|
|
75
|
+
<line num="339" count="1" type="stmt"/>
|
|
76
|
+
<line num="340" count="1" type="stmt"/>
|
|
77
|
+
<line num="364" count="3" type="stmt"/>
|
|
78
|
+
<line num="365" count="3" type="stmt"/>
|
|
79
|
+
<line num="366" count="3" type="stmt"/>
|
|
80
|
+
<line num="368" count="2" type="cond" truecount="2" falsecount="0"/>
|
|
81
|
+
<line num="369" count="1" type="stmt"/>
|
|
82
|
+
<line num="373" count="2" type="stmt"/>
|
|
83
|
+
<line num="374" count="1" type="stmt"/>
|
|
84
|
+
<line num="376" count="1" type="stmt"/>
|
|
85
|
+
<line num="377" count="1" type="stmt"/>
|
|
86
|
+
<line num="379" count="1" type="stmt"/>
|
|
87
|
+
<line num="380" count="1" type="stmt"/>
|
|
88
|
+
<line num="400" count="3" type="stmt"/>
|
|
89
|
+
<line num="401" count="3" type="stmt"/>
|
|
90
|
+
<line num="402" count="3" type="stmt"/>
|
|
91
|
+
<line num="403" count="2" type="stmt"/>
|
|
92
|
+
<line num="405" count="1" type="stmt"/>
|
|
93
|
+
<line num="406" count="1" type="stmt"/>
|
|
94
|
+
<line num="431" count="4" type="stmt"/>
|
|
95
|
+
<line num="432" count="4" type="stmt"/>
|
|
96
|
+
<line num="433" count="4" type="stmt"/>
|
|
97
|
+
<line num="435" count="1" type="stmt"/>
|
|
98
|
+
<line num="436" count="1" type="stmt"/>
|
|
99
|
+
<line num="456" count="3" type="stmt"/>
|
|
100
|
+
<line num="457" count="3" type="stmt"/>
|
|
101
|
+
<line num="458" count="3" type="stmt"/>
|
|
102
|
+
<line num="459" count="2" type="stmt"/>
|
|
103
|
+
<line num="461" count="1" type="stmt"/>
|
|
104
|
+
<line num="462" count="1" type="stmt"/>
|
|
105
|
+
<line num="485" count="4" type="stmt"/>
|
|
106
|
+
<line num="486" count="4" type="stmt"/>
|
|
107
|
+
<line num="488" count="4" type="cond" truecount="2" falsecount="0"/>
|
|
108
|
+
<line num="489" count="3" type="stmt"/>
|
|
109
|
+
<line num="491" count="1" type="stmt"/>
|
|
110
|
+
<line num="494" count="1" type="stmt"/>
|
|
111
|
+
<line num="495" count="1" type="stmt"/>
|
|
112
|
+
<line num="517" count="3" type="stmt"/>
|
|
113
|
+
<line num="518" count="3" type="stmt"/>
|
|
114
|
+
<line num="520" count="3" type="cond" truecount="2" falsecount="0"/>
|
|
115
|
+
<line num="521" count="2" type="stmt"/>
|
|
116
|
+
<line num="523" count="1" type="stmt"/>
|
|
117
|
+
<line num="526" count="1" type="stmt"/>
|
|
118
|
+
<line num="527" count="1" type="stmt"/>
|
|
119
|
+
<line num="547" count="3" type="stmt"/>
|
|
120
|
+
<line num="548" count="7" type="stmt"/>
|
|
121
|
+
<line num="549" count="3" type="stmt"/>
|
|
122
|
+
<line num="551" count="2" type="stmt"/>
|
|
123
|
+
<line num="552" count="2" type="stmt"/>
|
|
124
|
+
<line num="553" count="6" type="cond" truecount="2" falsecount="0"/>
|
|
125
|
+
<line num="554" count="4" type="stmt"/>
|
|
126
|
+
<line num="555" count="4" type="stmt"/>
|
|
127
|
+
<line num="556" count="2" type="stmt"/>
|
|
128
|
+
<line num="558" count="2" type="stmt"/>
|
|
129
|
+
<line num="559" count="2" type="stmt"/>
|
|
130
|
+
<line num="562" count="2" type="stmt"/>
|
|
131
|
+
<line num="566" count="2" type="stmt"/>
|
|
132
|
+
<line num="568" count="1" type="stmt"/>
|
|
133
|
+
<line num="569" count="1" type="stmt"/>
|
|
134
|
+
<line num="592" count="2" type="stmt"/>
|
|
135
|
+
<line num="593" count="2" type="stmt"/>
|
|
136
|
+
<line num="595" count="2" type="stmt"/>
|
|
137
|
+
<line num="596" count="3" type="stmt"/>
|
|
138
|
+
<line num="597" count="3" type="cond" truecount="2" falsecount="0"/>
|
|
139
|
+
<line num="598" count="3" type="cond" truecount="2" falsecount="0"/>
|
|
140
|
+
<line num="600" count="3" type="cond" truecount="1" falsecount="1"/>
|
|
141
|
+
<line num="601" count="3" type="stmt"/>
|
|
142
|
+
<line num="603" count="0" type="stmt"/>
|
|
143
|
+
<line num="606" count="3" type="stmt"/>
|
|
144
|
+
<line num="609" count="2" type="stmt"/>
|
|
145
|
+
<line num="610" count="1" type="stmt"/>
|
|
146
|
+
<line num="612" count="1" type="stmt"/>
|
|
147
|
+
<line num="613" count="1" type="stmt"/>
|
|
148
|
+
<line num="635" count="4" type="cond" truecount="2" falsecount="0"/>
|
|
149
|
+
<line num="636" count="2" type="stmt"/>
|
|
150
|
+
<line num="639" count="2" type="stmt"/>
|
|
151
|
+
<line num="641" count="2" type="stmt"/>
|
|
152
|
+
<line num="643" count="1" type="cond" truecount="1" falsecount="1"/>
|
|
153
|
+
<line num="644" count="2" type="stmt"/>
|
|
154
|
+
<line num="645" count="1" type="stmt"/>
|
|
155
|
+
<line num="648" count="1" type="stmt"/>
|
|
156
|
+
<line num="650" count="1" type="stmt"/>
|
|
157
|
+
<line num="651" count="1" type="stmt"/>
|
|
158
|
+
<line num="673" count="5" type="stmt"/>
|
|
159
|
+
<line num="692" count="2" type="stmt"/>
|
|
160
|
+
<line num="717" count="1" type="stmt"/>
|
|
161
|
+
<line num="760" count="2" type="cond" truecount="2" falsecount="0"/>
|
|
162
|
+
<line num="761" count="2" type="cond" truecount="2" falsecount="1"/>
|
|
163
|
+
<line num="762" count="2" type="cond" truecount="2" falsecount="0"/>
|
|
164
|
+
<line num="763" count="3" type="stmt"/>
|
|
165
|
+
<line num="764" count="3" type="stmt"/>
|
|
166
|
+
<line num="765" count="3" type="stmt"/>
|
|
167
|
+
<line num="768" count="2" type="stmt"/>
|
|
168
|
+
<line num="769" count="3" type="stmt"/>
|
|
169
|
+
<line num="772" count="3" type="stmt"/>
|
|
170
|
+
<line num="773" count="3" type="cond" truecount="2" falsecount="0"/>
|
|
171
|
+
<line num="774" count="1" type="stmt"/>
|
|
172
|
+
<line num="778" count="2" type="stmt"/>
|
|
173
|
+
<line num="781" count="1" type="stmt"/>
|
|
174
|
+
<line num="783" count="1" type="stmt"/>
|
|
175
|
+
<line num="802" count="3" type="stmt"/>
|
|
176
|
+
<line num="803" count="3" type="stmt"/>
|
|
177
|
+
<line num="804" count="1" type="stmt"/>
|
|
178
|
+
<line num="806" count="2" type="stmt"/>
|
|
179
|
+
<line num="857" count="2" type="stmt"/>
|
|
180
|
+
<line num="872" count="2" type="stmt"/>
|
|
181
|
+
<line num="878" count="2" type="stmt"/>
|
|
182
|
+
<line num="881" count="2" type="stmt"/>
|
|
183
|
+
<line num="883" count="0" type="stmt"/>
|
|
184
|
+
<line num="884" count="0" type="stmt"/>
|
|
185
|
+
<line num="887" count="0" type="stmt"/>
|
|
186
|
+
<line num="888" count="0" type="stmt"/>
|
|
187
|
+
<line num="891" count="0" type="cond" truecount="0" falsecount="2"/>
|
|
188
|
+
<line num="892" count="0" type="stmt"/>
|
|
189
|
+
<line num="893" count="0" type="stmt"/>
|
|
190
|
+
<line num="895" count="0" type="stmt"/>
|
|
191
|
+
<line num="896" count="0" type="stmt"/>
|
|
192
|
+
<line num="900" count="0" type="stmt"/>
|
|
193
|
+
<line num="901" count="0" type="stmt"/>
|
|
194
|
+
<line num="903" count="0" type="cond" truecount="0" falsecount="2"/>
|
|
195
|
+
<line num="904" count="0" type="stmt"/>
|
|
196
|
+
<line num="906" count="0" type="stmt"/>
|
|
197
|
+
<line num="910" count="0" type="stmt"/>
|
|
198
|
+
<line num="911" count="0" type="stmt"/>
|
|
199
|
+
<line num="915" count="0" type="stmt"/>
|
|
200
|
+
<line num="916" count="0" type="stmt"/>
|
|
201
|
+
<line num="919" count="0" type="stmt"/>
|
|
202
|
+
<line num="921" count="0" type="stmt"/>
|
|
203
|
+
</file>
|
|
204
|
+
</project>
|
|
205
|
+
</coverage>
|