Skip to content

Commit 2c5b309

Browse files
committed
add unit tests
1 parent 16e8a7e commit 2c5b309

File tree

3 files changed

+238
-0
lines changed

3 files changed

+238
-0
lines changed

tests/unit/models/BucketLoggingStatus.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,5 +306,29 @@ describe('BucketLoggingStatus', () => {
306306
assert.strictEqual(result.res.getLoggingEnabled(), undefined);
307307
});
308308
});
309+
310+
describe('XML escaping for special characters', () => {
311+
const specialCharacters = ['&', '<', '>', '"', "'"];
312+
313+
specialCharacters.forEach(char =>
314+
it(`should escape \`${char}\` in TargetPrefix and generate valid XML`, done => {
315+
const loggingEnabled = {
316+
TargetBucket: 'test-bucket',
317+
TargetPrefix: `logs/app${char}env/`,
318+
};
319+
const config = new BucketLoggingStatus(loggingEnabled);
320+
const xml = config.toXML();
321+
322+
// Verify the XML is valid and the character roundtrips by parsing it
323+
parseString(xml, { explicitArray: false }, (err, result) => {
324+
assert.ifError(err);
325+
assert(result.BucketLoggingStatus);
326+
const logging = result.BucketLoggingStatus.LoggingEnabled;
327+
assert.strictEqual(logging.TargetPrefix, `logs/app${char}env/`);
328+
done();
329+
});
330+
})
331+
);
332+
});
309333
});
310334
});

tests/unit/models/LifecycleConfiguration.spec.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,3 +1396,85 @@ describe('LifecycleConfiguration::getConfigJson', () => {
13961396
);
13971397
}));
13981398
});
1399+
1400+
describe('LifecycleConfiguration.getConfigXml - XML escaping for special characters', () => {
1401+
const specialCharacters = ['&', '<', '>', '"', "'"];
1402+
1403+
specialCharacters.forEach(char => {
1404+
it(`should escape \`${char}\` in rule ID and generate valid XML`, done => {
1405+
const config = {
1406+
rules: [{
1407+
ruleID: `test-id${char}value`,
1408+
ruleStatus: 'Enabled',
1409+
prefix: 'logs/',
1410+
actions: [{
1411+
actionName: 'Expiration',
1412+
days: 90,
1413+
}],
1414+
}],
1415+
};
1416+
1417+
const xml = LifecycleConfiguration.getConfigXml(config);
1418+
1419+
parseString(xml, (err, result) => {
1420+
assert.ifError(err);
1421+
const rule = result.LifecycleConfiguration.Rule[0];
1422+
assert.strictEqual(rule.ID[0], `test-id${char}value`);
1423+
done();
1424+
});
1425+
});
1426+
1427+
it(`should escape \`${char}\` in prefix`, done => {
1428+
const config = {
1429+
rules: [{
1430+
ruleID: 'test-id',
1431+
ruleStatus: 'Enabled',
1432+
prefix: `logs/${char}path/`,
1433+
actions: [{
1434+
actionName: 'Expiration',
1435+
days: 90,
1436+
}],
1437+
}],
1438+
};
1439+
1440+
const xml = LifecycleConfiguration.getConfigXml(config);
1441+
1442+
parseString(xml, (err, result) => {
1443+
assert.ifError(err);
1444+
const rule = result.LifecycleConfiguration.Rule[0];
1445+
assert.strictEqual(rule.Prefix[0], `logs/${char}path/`);
1446+
done();
1447+
});
1448+
});
1449+
1450+
it(`should escape \`${char}\` in tag key and value`, done => {
1451+
const config = {
1452+
rules: [{
1453+
ruleID: 'test-id',
1454+
ruleStatus: 'Enabled',
1455+
filter: {
1456+
tags: [{
1457+
key: `env${char}key`,
1458+
val: `value${char}data`,
1459+
}],
1460+
},
1461+
actions: [{
1462+
actionName: 'Expiration',
1463+
days: 90,
1464+
}],
1465+
}],
1466+
};
1467+
1468+
const xml = LifecycleConfiguration.getConfigXml(config);
1469+
1470+
parseString(xml, (err, result) => {
1471+
assert.ifError(err);
1472+
const rule = result.LifecycleConfiguration.Rule[0];
1473+
const tag = rule.Filter[0].Tag[0];
1474+
assert.strictEqual(tag.Key[0], `env${char}key`);
1475+
assert.strictEqual(tag.Value[0], `value${char}data`);
1476+
done();
1477+
});
1478+
});
1479+
});
1480+
});

tests/unit/models/NotificationConfiguration.spec.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,135 @@ describe('NotificationConfiguration.restrictSupportedNotificationBasedOnLifecycl
290290
expect(supportedNotificationEvents.has('s3:ObjectCreated:*')).toBeTruthy();
291291
});
292292
});
293+
294+
describe('NotificationConfiguration.getConfigXML - XML escaping for special characters', () => {
295+
const specialCharacters = ['&', '<', '>', '"', "'"];
296+
297+
specialCharacters.forEach(char =>
298+
it(`should escape \`${char}\` in notification ID and generate valid XML`, done => {
299+
const config = {
300+
queueConfig: [{
301+
id: `test-id${char}value`,
302+
queueArn: 'arn:scality:bucketnotif:::target',
303+
events: ['s3:ObjectCreated:*'],
304+
filterRules: [],
305+
}],
306+
};
307+
308+
const xml = NotificationConfiguration.getConfigXML(config);
309+
310+
parseString(xml, (err, result) => {
311+
assert.ifError(err);
312+
const queueConfig = result.NotificationConfiguration.QueueConfiguration[0];
313+
assert.strictEqual(queueConfig.Id[0], `test-id${char}value`);
314+
done();
315+
});
316+
})
317+
);
318+
319+
specialCharacters.forEach(char =>
320+
it(`should escape \`${char}\` in queue ARN`, done => {
321+
const config = {
322+
queueConfig: [{
323+
id: 'test-id',
324+
queueArn: `arn:scality:bucketnotif:::queue${char}name`,
325+
events: ['s3:ObjectCreated:*'],
326+
filterRules: [],
327+
}],
328+
};
329+
330+
const xml = NotificationConfiguration.getConfigXML(config);
331+
332+
parseString(xml, (err, result) => {
333+
assert.ifError(err);
334+
const queueConfig = result.NotificationConfiguration.QueueConfiguration[0];
335+
assert.strictEqual(queueConfig.Queue[0], `arn:scality:bucketnotif:::queue${char}name`);
336+
done();
337+
});
338+
})
339+
);
340+
341+
specialCharacters.forEach(char =>
342+
it(`should escape \`${char}\` in filter rule name and value`, done => {
343+
const config = {
344+
queueConfig: [{
345+
id: 'test-id',
346+
queueArn: 'arn:scality:bucketnotif:::target',
347+
events: ['s3:ObjectCreated:*'],
348+
filterRules: [{
349+
name: `Prefix${char}Name`,
350+
value: `logs/${char}path`,
351+
}],
352+
}],
353+
};
354+
355+
const xml = NotificationConfiguration.getConfigXML(config);
356+
357+
parseString(xml, (err, result) => {
358+
assert.ifError(err);
359+
const queueConfig = result.NotificationConfiguration.QueueConfiguration[0];
360+
const filterRule = queueConfig.Filter[0].S3Key[0].FilterRule[0];
361+
assert.strictEqual(filterRule.Name[0], `Prefix${char}Name`);
362+
assert.strictEqual(filterRule.Value[0], `logs/${char}path`);
363+
done();
364+
});
365+
})
366+
);
367+
368+
it('should escape multiple special characters across all fields', done => {
369+
const config = {
370+
queueConfig: [{
371+
id: 'id<test>&\'data\'',
372+
queueArn: 'arn:scality:bucketnotif:::target&<queue>',
373+
events: ['s3:ObjectCreated:*'],
374+
filterRules: [{
375+
name: 'Prefix',
376+
value: '<path>&"value"',
377+
}],
378+
}],
379+
};
380+
381+
const xml = NotificationConfiguration.getConfigXML(config);
382+
383+
parseString(xml, (err, result) => {
384+
assert.ifError(err);
385+
const queueConfig = result.NotificationConfiguration.QueueConfiguration[0];
386+
assert.strictEqual(queueConfig.Id[0], 'id<test>&\'data\'');
387+
assert.strictEqual(queueConfig.Queue[0], 'arn:scality:bucketnotif:::target&<queue>');
388+
const filterRule = queueConfig.Filter[0].S3Key[0].FilterRule[0];
389+
assert.strictEqual(filterRule.Value[0], '<path>&"value"');
390+
done();
391+
});
392+
});
393+
394+
it('should handle multiple filter rules with special characters', done => {
395+
const config = {
396+
queueConfig: [{
397+
id: 'test-id',
398+
queueArn: 'arn:scality:bucketnotif:::target',
399+
events: ['s3:ObjectCreated:*'],
400+
filterRules: [
401+
{
402+
name: 'Prefix',
403+
value: 'logs/<app>&env',
404+
},
405+
{
406+
name: 'Suffix',
407+
value: '.log&.txt',
408+
},
409+
],
410+
}],
411+
};
412+
413+
const xml = NotificationConfiguration.getConfigXML(config);
414+
415+
parseString(xml, (err, result) => {
416+
assert.ifError(err);
417+
const queueConfig = result.NotificationConfiguration.QueueConfiguration[0];
418+
const filterRules = queueConfig.Filter[0].S3Key[0].FilterRule;
419+
assert.strictEqual(filterRules[0].Value[0], 'logs/<app>&env');
420+
assert.strictEqual(filterRules[1].Value[0], '.log&.txt');
421+
done();
422+
});
423+
});
424+
});

0 commit comments

Comments
 (0)