Compare commits

...

2 Commits

Author SHA1 Message Date
Dora Korpar 77836d57c5 check s3 tests work 2018-03-12 15:40:43 -07:00
Dora Korpar e5fe2d2b7f bf: minor lifecycle fixes 2018-03-12 14:57:23 -07:00
4 changed files with 274 additions and 170 deletions

View File

@ -220,6 +220,10 @@
"code": 400,
"description": "Request body is empty"
},
"MissingRequiredParameter": {
"code": 400,
"description": "Your request is missing a required parameter."
},
"MissingSecurityElement": {
"code": 400,
"description": "The SOAP 1.1 request is missing a security element."

View File

@ -127,8 +127,8 @@ class LifecycleConfiguration {
const rulesArray = lifecycleConf.Rule;
if (!rulesArray || !Array.isArray(rulesArray)
|| rulesArray.length === 0) {
rules.error = errors.MalformedXML.customizeDescription(
'request xml does not include at least one rule');
rules.error = errors.MissingRequiredParameter.customizeDescription(
'missing required key \'Rules\' in LifecycleConfiguration');
return rules;
}
if (rulesArray.length > 1000) {
@ -197,8 +197,8 @@ class LifecycleConfiguration {
return ruleObj;
}
if (!rule.Status) {
ruleObj.error = errors.MalformedXML.customizeDescription(
'Rule xml does not include Status');
ruleObj.error = errors.MissingRequiredParameter.
customizeDescription('Rule xml does not include Status');
return ruleObj;
}
const subFilter = rule.Filter ? rule.Filter[0] : rule.Prefix;
@ -254,12 +254,8 @@ class LifecycleConfiguration {
filterObj.rulePrefix = '';
if (Array.isArray(filter)) {
// if Prefix was included, not Filter, filter will be Prefix array
if (filter.length > 1) {
filterObj.error = errors.MalformedXML.customizeDescription(
'Rule includes more than one Prefix');
return filterObj;
}
filterObj.rulePrefix = filter[0];
// if more than one Prefix is included, we ignore all but the last
filterObj.rulePrefix = filter.pop();
return filterObj;
}
if (filter.And && (filter.Prefix || filter.Tag) ||
@ -269,12 +265,7 @@ class LifecycleConfiguration {
return filterObj;
}
if (filter.Prefix) {
if (filter.Prefix.length > 1) {
filterObj.error = errors.MalformedXML.customizeDescription(
'Filter includes more than one Prefix');
return filterObj;
}
filterObj.rulePrefix = filter.Prefix[0];
filterObj.rulePrefix = filter.Prefix.pop();
return filterObj;
}
if (filter.Tag) {
@ -288,22 +279,19 @@ class LifecycleConfiguration {
}
if (filter.And) {
const andF = filter.And[0];
if (!andF.Tag || (!andF.Prefix && andF.Tag.length < 2)) {
if (!andF.Tags || (!andF.Prefix && andF.Tags.length < 2)) {
filterObj.error = errors.MalformedXML.customizeDescription(
'And should include Prefix and Tag or more than one Tag');
'And should include Prefix and Tags or more than one Tag');
return filterObj;
}
if (andF.Prefix && andF.Prefix.length > 1) {
filterObj.error = errors.MalformedXML.customizeDescription(
'And includes more than one Prefix');
return filterObj;
if (andF.Prefix && andF.Prefix.length >= 1) {
filterObj.rulePrefix = andF.Prefix.pop();
}
const tagObj = this._parseTags(andF.Tag[0]);
const tagObj = this._parseTags(andF.Tags[0]);
if (tagObj.error) {
filterObj.error = tagObj.error;
return filterObj;
}
filterObj.rulePrefix = andF.Prefix ? andF.Prefix[0] : null;
filterObj.tags = tagObj.tags;
return filterObj;
}
@ -329,8 +317,11 @@ class LifecycleConfiguration {
_parseTags(tags) {
const tagObj = {};
tagObj.tags = [];
// reset _tagKeys to empty because keys cannot overlap within a rule,
// but different rules can have the same tag keys
this._tagKeys = [];
if (!tags.Key || !tags.Value) {
tagObj.error = errors.MalformedXML.customizeDescription(
tagObj.error = errors.MissingRequiredParameter.customizeDescription(
'Tag XML does not contain both Key and Value');
return tagObj;
}
@ -414,7 +405,7 @@ class LifecycleConfiguration {
_parseStatus(status) {
const statusObj = {};
statusObj.propName = 'ruleStatus';
const validStatuses = ['Enabled', 'Suspended'];
const validStatuses = ['Enabled', 'Disabled'];
if (!validStatuses.includes(status)) {
statusObj.error = errors.MalformedXML.customizeDescription(
'Status is not valid');
@ -456,7 +447,7 @@ class LifecycleConfiguration {
}
});
if (actionsObj.actions.length === 0) {
actionsObj.error = errors.MalformedXML.customizeDescription(
actionsObj.error = errors.InvalidRequest.customizeDescription(
'Rule does not include valid action');
return actionsObj;
}
@ -501,7 +492,7 @@ class LifecycleConfiguration {
}
}
if (filter && filter.Tag) {
abortObj.error = errors.MalformedXML.customizeDescription(
abortObj.error = errors.InvalidRequest.customizeDescription(
'Tag-based filter cannot be used with ' +
'AbortIncompleteMultipartUpload action');
return abortObj;
@ -515,7 +506,7 @@ class LifecycleConfiguration {
}
const daysInt = parseInt(subAbort.DaysAfterInitiation[0], 10);
if (daysInt < 1) {
abortObj.error = errors.MalformedXML.customizeDescription(
abortObj.error = errors.InvalidArgument.customizeDescription(
'DaysAfterInitiation is not a positive integer');
return abortObj;
}
@ -540,19 +531,25 @@ class LifecycleConfiguration {
_parseExpiration(rule) {
const expObj = {};
const subExp = rule.Expiration[0];
if (!subExp.Date && !subExp.Days && !subExp.ExpiredObjDeleteMarker) {
if (!subExp.Date && !subExp.Days && !subExp.ExpiredObjectDeleteMarker) {
expObj.error = errors.MalformedXML.customizeDescription(
'Expiration action does not include an action time');
return expObj;
}
const eodm = 'ExpiredObjectDeleteMarker';
if (subExp.Date && (subExp.Days || subExp[eodm]) ||
(subExp.Days && subExp[eodm])) {
expObj.error = errors.MalformedXML.customizeDescription(
'Expiration action includes more than one time');
return expObj;
}
if (subExp.Date) {
const isoRegex = new RegExp('^(-?(?:[1-9][0-9]*)?[0-9]{4})-' +
'(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1]' +
'[0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]' +
'|[0-1][0-9]):[0-5][0-9])?$');
'(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9])' +
':([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$');
if (!isoRegex.test(subExp.Date[0])) {
expObj.error = errors.MalformedXML.customizeDescription(
'Date is not in proper ISO 8601 format');
expObj.error = errors.InvalidArgument.customizeDescription(
'Date must be in ISO 8601 format');
} else {
expObj.date = subExp.Date[0];
}
@ -560,19 +557,33 @@ class LifecycleConfiguration {
if (subExp.Days) {
const daysInt = parseInt(subExp.Days[0], 10);
if (daysInt < 1) {
expObj.error = errors.MalformedXML.customizeDescription(
expObj.error = errors.InvalidArgument.customizeDescription(
'Expiration days is not a positive integer');
} else {
expObj.days = daysInt;
}
}
if (subExp.ExpiredObjDeleteMarker) {
if (subExp.ExpiredObjectDeleteMarker) {
let filter = null;
if (rule.Filter && rule.Filter[0]) {
if (rule.Filter[0].And) {
filter = rule.Filter[0].And[0];
} else {
filter = rule.Filter[0];
}
}
if (filter && filter.Tag) {
expObj.error = errors.InvalidRequest.customizeDescription(
'Tag-based filter cannot be used with ' +
'ExpiredObjectDeleteMarker action');
return expObj;
}
const validValues = ['true', 'false'];
if (!validValues.includes(subExp.ExpiredObjDeleteMarker[0])) {
if (!validValues.includes(subExp.ExpiredObjectDeleteMarker[0])) {
expObj.error = errors.MalformedXML.customizeDescription(
'ExpiredObjDeleteMarker is not true or false');
} else {
expObj.deleteMarker = subExp.ExpiredObjDeleteMarker[0];
expObj.deleteMarker = subExp.ExpiredObjectDeleteMarker[0];
}
}
return expObj;
@ -601,7 +612,7 @@ class LifecycleConfiguration {
}
const daysInt = parseInt(subNVExp.NoncurrentDays[0], 10);
if (daysInt < 1) {
nvExpObj.error = errors.MalformedXML.customizeDescription(
nvExpObj.error = errors.InvalidArgument.customizeDescription(
'NoncurrentDays is not a positive integer');
} else {
nvExpObj.days = daysInt;
@ -666,12 +677,20 @@ class LifecycleConfiguration {
const Prefix = rulePrefix ? `<Prefix>${rulePrefix}</Prefix>` : '';
let tagXML = '';
if (tags) {
tagXML = tags.map(t => {
const { key, val } = t;
const Tag = `<Tag><Key>${key}</Key>` +
if (Prefix || tags.length > 1) {
const keysVals = tags.map(t => {
const { key, val } = t;
const Tag = `<Key>${key}</Key>` +
`<Value>${val}</Value>`;
return Tag;
}).join('');
tagXML = `<Tags>${keysVals}</Tags>`;
} else {
// only one tag included
const { key, val } = tags[0];
tagXML = `<Tag><Key>${key}</Key>` +
`<Value>${val}</Value></Tag>`;
return Tag;
}).join('');
}
}
let Filter;
if (rulePrefix && !tags) {
@ -686,7 +705,7 @@ class LifecycleConfiguration {
const Actions = actions.map(action => {
const { actionName, days, date, deleteMarker } = action;
let Action;
if (actionName === 'AbortIncompleteMultipartUploads') {
if (actionName === 'AbortIncompleteMultipartUpload') {
Action = `<${actionName}><DaysAfterInitiation>${days}` +
`</DaysAfterInitiation></${actionName}>`;
} else if (actionName === 'NoncurrentVersionExpiration') {

View File

@ -3,7 +3,7 @@
"engines": {
"node": "6.9.5"
},
"version": "7.4.0",
"version": "7.4.0-foo",
"description": "Common utilities for the S3 project components",
"main": "index.js",
"repository": {

View File

@ -4,6 +4,15 @@ const { parseString } = require('xml2js');
const LifecycleConfiguration =
require('../../../lib/models/LifecycleConfiguration.js');
const days = {
AbortIncompleteMultipartUpload: 'DaysAfterInitiation',
NoncurrentVersionExpiration: 'NoncurrentDays',
Expiration: 'Days',
};
const date = new Date();
date.setUTCHours(0, 0, 0, 0);
/**
* Format of xml request:
<LifecycleConfiguration>
@ -37,32 +46,17 @@ const LifecycleConfiguration =
*/
const requiredTags = [
{ tag: 'LifecycleConfiguration',
{ tag: 'LifecycleConfiguration', error: 'MalformedXML',
errMessage: 'request xml is undefined or empty' },
{ tag: 'Rule',
errMessage: 'request xml does not include at least one rule' },
{ tag: 'Status', errMessage: 'Rule xml does not include Status' },
{ tag: 'Filter', errMessage: 'Rule xml does not include valid Filter ' +
'or Prefix' },
{ tag: 'Action', errMessage: 'Rule does not include valid action' }];
const validActions = [
{ tag: 'Expiration',
errMessage: 'Expiration action does not include an action time' },
{ tag: 'NoncurrentVersionExpiration',
errMessage: 'NoncurrentVersionExpiration action does not include ' +
'NoncurrentDays' },
{ tag: 'AbortIncompleteMultipartUpload',
errMessage: 'AbortIncompleteMultipartUpload action does not ' +
'include DaysAfterInitiation' }];
const invalidActions = [
{ tag: 'foo', errMessage: 'Rule does not include valid action' },
{ tag: 'invalid-days-value',
errMessage: 'Expiration days is not a positive integer' },
{ tag: 'abortMPU-tag',
errMessage: 'Tag-based filter cannot be used with ' +
'AbortIncompleteMultipartUpload action' }];
{ tag: 'Rule', error: 'MissingRequiredParameter',
errMessage: 'missing required key \'Rules\' in ' +
'LifecycleConfiguration' },
{ tag: 'Status', error: 'MissingRequiredParameter',
errMessage: 'Rule xml does not include Status' },
{ tag: 'Filter', error: 'MalformedXML',
errMessage: 'Rule xml does not include valid Filter or Prefix' },
{ tag: 'Action', error: 'InvalidRequest',
errMessage: 'Rule does not include valid action' }];
const notImplementedActions = [
{ tag: 'Transition',
@ -70,100 +64,175 @@ const notImplementedActions = [
{ tag: 'NoncurrentVersionTransition',
errMessage: 'Transition lifecycle action not yet implemented' }];
const invalidFilters = [
{ tag: 'two-prefixes',
errMessage: 'Filter includes more than one Prefix' },
{ tag: 'invalid-tag',
errMessage: 'Tag XML does not contain both Key and Value' }];
const invalidActions = [
{ tag: 'AbortIncompleteMultipartUpload', label: 'no-time',
error: 'MalformedXML',
errMessage: 'AbortIncompleteMultipartUpload action does not ' +
'include DaysAfterInitiation' },
{ tag: 'AbortIncompleteMultipartUpload', label: 'no-tags',
error: 'InvalidRequest', errMessage: 'Tag-based filter cannot be ' +
'used with AbortIncompleteMultipartUpload action' },
{ tag: 'AbortIncompleteMultipartUpload', label: 'invalid-days',
error: 'InvalidArgument',
errMessage: 'DaysAfterInitiation is not a positive integer' },
{ tag: 'Expiration', label: 'no-time', error: 'MalformedXML',
errMessage: 'Expiration action does not include an action time' },
{ tag: 'Expiration', label: 'mult-times', error: 'MalformedXML',
errMessage: 'Expiration action includes more than one time' },
{ tag: 'Expiration', label: 'non-iso', error: 'InvalidArgument',
errMessage: 'Date must be in ISO 8601 format' },
{ tag: 'Expiration', label: 'invalid-days', error: 'InvalidArgument',
errMessage: 'Expiration days is not a positive integer' },
{ tag: 'Expiration', label: 'no-tags', inTag: 'ExpiredObjectDeleteMarker',
error: 'InvalidRequest',
errMessage: 'Tag-based filter cannot be used with ' +
'ExpiredObjectDeleteMarker action' },
{ tag: 'Expiration', label: 'invalid-eodm', error: 'MalformedXML',
errMessage: 'ExpiredObjDeleteMarker is not true or false' },
{ tag: 'NoncurrentVersionExpiration', label: 'no-time',
error: 'MalformedXML',
errMessage: 'NoncurrentVersionExpiration action does not include ' +
'NoncurrentDays' },
{ tag: 'NoncurrentVersionExpiration', label: 'invalid-days',
error: 'InvalidArgument',
errMessage: 'NoncurrentDays is not a positive integer' }];
const invalidRequests = [
{ tag: 'not-unique-id',
errMessage: 'Rule ID must be unique' },
{ tag: 'key-too-long',
const invalidFilters = [
{ tag: 'Filter', label: 'also-prefix', error: 'MalformedXML',
errMessage: 'Rule xml should not include both Filter and Prefix' },
{ tag: 'Filter', label: 'and-prefix-tag', error: 'MalformedXML',
errMessage: 'Filter should only include one of And, Prefix, or ' +
'Tag key' },
{ tag: 'And', label: 'only-prefix', error: 'MalformedXML',
errMessage: 'And should include Prefix and Tags or more than one Tag' },
{ tag: 'And', label: 'single-tag', error: 'MalformedXML',
errMessage: 'And should include Prefix and Tags or more than one Tag' },
{ tag: 'Tag', label: 'no-key', error: 'MissingRequiredParameter',
errMessage: 'Tag XML does not contain both Key and Value' },
{ tag: 'Tag', label: 'no-value', error: 'MissingRequiredParameter',
errMessage: 'Tag XML does not contain both Key and Value' },
{ tag: 'Tag', label: 'key-too-long', error: 'InvalidRequest',
errMessage: 'Tag Key must be a length between 1 and 128 char' }];
function generateFilter(errorTag, tagValue) {
function generateAction(errorTag, tagObj) {
const xmlObj = {};
if (tagObj) {
let middleTags = '';
if (tagObj.label === 'no-time') {
middleTags = '';
}
if (tagObj.label === 'no-tags') {
middleTags = tagObj.inTag ?
`<${tagObj.inTag}>true</${tagObj.inTag}>` :
`<${days[tagObj.tag]}>1</${days[tagObj.tag]}>`;
xmlObj.filter = '<Filter><Tag><Key>key</Key>' +
'<Value></Value></Tag></Filter>';
}
if (tagObj.label === 'invalid-days') {
middleTags = `<${days[tagObj.tag]}>0</${days[tagObj.tag]}>`;
}
if (tagObj.label === 'mult-times') {
middleTags = `<Days>1</Days><Date>${date}</Date>`;
}
if (tagObj.label === 'non-iso') {
middleTags = '<Date>03-08-2018</Date>';
}
if (tagObj.label === 'invalid-eodm') {
middleTags = '<ExpiredObjectDeleteMarker>foo' +
'</ExpiredObjectDeleteMarker>';
}
xmlObj.actions = `<${tagObj.tag}>${middleTags}</${tagObj.tag}>`;
} else {
xmlObj.actions = '';
}
return xmlObj;
}
function generateFilter(errorTag, tagObj) {
let Filter;
if (tagValue && tagValue.filter === 'two-prefixes') {
Filter = '<Filter><Prefix>foo</Prefix>' +
'<Prefix>foo2</Prefix></Filter>';
} else if (tagValue && tagValue.filter === 'invalid-tag') {
Filter = '<Filter><Tag></Tag></Filter>';
let middleTags = '';
if (tagObj) {
if (tagObj.label === 'and-prefix-tag') {
middleTags = '<And></And><Prefix></Prefix><Tag></Tag>';
}
if (tagObj.label === 'only-prefix') {
middleTags = '<And><Prefix></Prefix></And>';
}
if (tagObj.label === 'single-tag') {
middleTags = '<And><Tags><Key>fo</Key><Value></Value></Tags></And>';
}
if (tagObj.label === 'no-key') {
middleTags = '<Tag><Value></Value></Tag>';
}
if (tagObj.label === 'no-value') {
middleTags = '<Tag><Key></Key></Tag>';
}
if (tagObj.label === 'key-too-long') {
const longKey = 'a'.repeat(129);
middleTags = `<Tag><Key>${longKey}</Key><Value></Value></Tag>`;
}
if (tagObj.label === 'mult-prefixes') {
middleTags = '<Prefix>foo</Prefix><Prefix>bar</Prefix>' +
`<Prefix>${tagObj.lastPrefix}</Prefix>`;
}
Filter = `<Filter>${middleTags}</Filter>`;
if (tagObj.label === 'also-prefix') {
Filter = '<Filter></Filter><Prefix></Prefix>';
}
} else {
Filter = '';
}
return Filter;
}
function generateAction(errorTag, tagValue) {
const xmlObj = {};
if (tagValue && tagValue.action === 'invalid-days-value') {
xmlObj.actions = '<Expiration><Days>0</Days></Expiration>';
} else if (tagValue && tagValue.action === 'abortMPU-tag') {
xmlObj.actions = '<AbortIncompleteMultipartUpload>' +
'</AbortIncompleteMultipartUpload>';
xmlObj.filter = '<Filter><Tag><Key>key</Key>' +
'<Value></Value></Tag></Filter>';
} else {
xmlObj.actions = tagValue && tagValue.action ?
`<${tagValue.action}></${tagValue.action}>` : '';
}
return xmlObj;
}
function generateRule(errorTag, tagValue, ID, Status, Filter, Action) {
function generateRule(errorTag, tagObj, ID, Status, Filter, Action) {
let Rule;
if (tagValue && tagValue.rule === 'not-unique-id') {
if (tagObj && tagObj.rule === 'not-unique-id') {
Rule = `<Rule>${ID + Status + Filter + Action}</Rule>` +
`<Rule>${ID + Status + Filter + Action}</Rule>`;
} else if (tagValue && tagValue.rule === 'too-many-rules') {
} else if (tagObj && tagObj.rule === 'too-many-rules') {
for (let i = 0; i <= 1000; i++) {
// eslint-disable-next-line no-param-reassign
ID = `<ID>foo${i}</ID>`;
Rule = `${Rule}<Rule>${ID + Status + Filter + Action}</Rule>`;
}
} else if (tagValue && tagValue.rule === 'key-too-long') {
const key = 'a'.repeat(129);
// eslint-disable-next-line no-param-reassign
Filter = `<Filter><Tag><Key>${key}</Key><Value></Value></Tag></Filter>`;
Rule = `${Rule}<Rule>${ID + Status + Filter + Action}</Rule>`;
} else {
Rule = '';
}
return Rule;
}
function generateXml(errorTag, tagValue) {
function generateXml(errorTag, tagObj) {
let ID;
let Status;
let Filter;
let Action;
let Rule;
if (errorTag === 'ID') {
ID = tagValue && tagValue.id ? `<ID>${tagValue.id}</ID>` : '';
ID = tagObj && tagObj.id ? `<ID>${tagObj.id}</ID>` : '';
} else {
ID = '<ID>foo</ID>';
}
if (errorTag === 'Status') {
Status = tagValue && tagValue.status ?
`<Status>${tagValue.status}</Status>` : '';
Status = tagObj && tagObj.status ?
`<Status>${tagObj.status}</Status>` : '';
} else {
Status = '<Status>Enabled</Status>';
}
if (errorTag === 'Filter') {
Filter = generateFilter(errorTag, tagValue);
Filter = generateFilter(errorTag, tagObj);
} else {
Filter = '<Filter></Filter>';
}
if (errorTag === 'Action') {
const xmlObj = generateAction(errorTag, tagValue);
const xmlObj = generateAction(errorTag, tagObj);
Action = xmlObj.actions;
Filter = xmlObj.filter ? xmlObj.filter : Filter;
} else {
Action = '<Expiration><Days>1</Days></Expiration>';
}
if (errorTag === 'Rule') {
Rule = generateRule(errorTag, tagValue, ID, Status, Filter, Action);
Rule = generateRule(errorTag, tagObj, ID, Status, Filter, Action);
} else {
Rule = `<Rule>${ID + Status + Filter + Action}</Rule>`;
}
@ -173,8 +242,8 @@ function generateXml(errorTag, tagValue) {
return Lifecycle;
}
function generateParsedXml(errorTag, tagValue, cb) {
const xml = generateXml(errorTag, tagValue);
function generateParsedXml(errorTag, tagObj, cb) {
const xml = generateXml(errorTag, tagObj);
parseString(xml, (err, parsedXml) => {
assert.equal(err, null, 'Error parsing xml');
cb(parsedXml);
@ -182,90 +251,102 @@ function generateParsedXml(errorTag, tagValue, cb) {
}
function checkError(parsedXml, error, errMessage, cb) {
const lifecycleConfig =
new LifecycleConfiguration(parsedXml).
const lcConfig = new LifecycleConfiguration(parsedXml).
getLifecycleConfiguration();
assert.strictEqual(
lifecycleConfig.error[error], true);
assert.strictEqual(
lifecycleConfig.error.description, errMessage);
assert.strictEqual(lcConfig.error[error], true);
assert.strictEqual(lcConfig.error.description, errMessage);
cb();
}
describe('LifecycleConfiguration class getLifecycleConfiguration', () => {
const tagValue = {};
requiredTags.forEach(tag => {
it(`should return MalformedXML error if ${tag.tag} tag is missing`,
let tagObj;
beforeEach(() => {
tagObj = {};
});
it('should return MalformedXML error if request xml is empty', done => {
const errMessage = 'request xml is undefined or empty';
checkError('', 'MalformedXML', errMessage, done);
});
requiredTags.forEach(t => {
it(`should return ${t.error} error if ${t.tag} tag is missing`,
done => {
generateParsedXml(tag.tag, tagValue, parsedXml => {
checkError(parsedXml, 'MalformedXML', tag.errMessage, done);
});
});
});
validActions.forEach(action => {
it(`should return MalformedXML error if time for ${action.tag} ` +
'is not included', done => {
tagValue.action = action.tag;
generateParsedXml('Action', tagValue, parsedXml => {
checkError(parsedXml, 'MalformedXML', action.errMessage, done);
});
});
});
invalidActions.forEach(action => {
it(`should return MalformedXML error for invalid action ${action.tag}`,
done => {
tagValue.action = action.tag;
generateParsedXml('Action', tagValue, parsedXml => {
checkError(parsedXml, 'MalformedXML', action.errMessage, done);
generateParsedXml(t.tag, null, parsedXml => {
checkError(parsedXml, t.error, t.errMessage, done);
});
});
});
notImplementedActions.forEach(action => {
it(`should return NotImplemented error for ${action.tag} action`,
const expError = 'NotImplemented';
it(`should return ${expError} error for ${action.tag} action`,
done => {
tagValue.action = action.tag;
generateParsedXml('Action', tagValue, parsedXml => {
checkError(parsedXml, 'NotImplemented',
action.errMessage, done);
generateParsedXml('Action', action, parsedXml => {
checkError(parsedXml, expError, action.errMessage, done);
});
});
});
invalidActions.forEach(a => {
it(`should return ${a.error} for ${a.label} action error`,
done => {
generateParsedXml('Action', a, parsedXml => {
checkError(parsedXml, a.error, a.errMessage, done);
});
});
});
invalidFilters.forEach(filter => {
it(`should return MalformedXML error for ${filter.tag} filter error`,
it(`should return ${filter.error} for ${filter.label} filter error`,
done => {
tagValue.filter = filter.tag;
generateParsedXml('Filter', tagValue, parsedXml => {
checkError(parsedXml, 'MalformedXML', filter.errMessage, done);
generateParsedXml('Filter', filter, parsedXml => {
checkError(parsedXml, filter.error, filter.errMessage, done);
});
});
});
it('should return MalformedXML error if invalid status', done => {
tagValue.status = 'foo';
tagObj.status = 'foo';
const errMessage = 'Status is not valid';
generateParsedXml('Status', tagValue, parsedXml => {
generateParsedXml('Status', tagObj, parsedXml => {
checkError(parsedXml, 'MalformedXML', errMessage, done);
});
});
it('should return InvalidRequest error if ID not unique', done => {
tagObj.rule = 'not-unique-id';
const errMessage = 'Rule ID must be unique';
generateParsedXml('Rule', tagObj, parsedXml => {
checkError(parsedXml, 'InvalidRequest', errMessage, done);
});
});
it('should return InvalidArgument error if invalid ID', done => {
tagValue.id = 'a'.repeat(256);
tagObj.id = 'a'.repeat(256);
const errMessage = 'Rule ID is greater than 255 characters long';
generateParsedXml('ID', tagValue, parsedXml => {
generateParsedXml('ID', tagObj, parsedXml => {
checkError(parsedXml, 'InvalidArgument', errMessage, done);
});
});
it('should return MalformedXML error if over 1000 rules', done => {
tagValue.rule = 'too-many-rules';
tagObj.rule = 'too-many-rules';
const errMessage = 'request xml includes over max limit of 1000 rules';
generateParsedXml('Rule', tagValue, parsedXml => {
generateParsedXml('Rule', tagObj, parsedXml => {
checkError(parsedXml, 'MalformedXML', errMessage, done);
});
});
invalidRequests.forEach(req => {
it(`should return InvalidRequest error for ${req.tag}`, done => {
tagValue.rule = req.tag;
generateParsedXml('Rule', tagValue, parsedXml => {
checkError(parsedXml, 'InvalidRequest', req.errMessage, done);
});
it('should use last listed Prefix if multiple Prefixes included', done => {
tagObj.label = 'mult-prefixes';
tagObj.lastPrefix = 'coco';
generateParsedXml('Filter', tagObj, parsedXml => {
const lcConfig = new LifecycleConfiguration(parsedXml).
getLifecycleConfiguration();
assert.strictEqual(tagObj.lastPrefix,
lcConfig.rules[0].filter.rulePrefix);
done();
});
});
});