Paws XXXII (80+ paws)
Today's post proves that test suite, even one that uses canned data, requests and responses, is a very valuable asset to have about.
As I was charging though some 80 action calls copying the requests from my successful unit tests into my t/09_request.t test cases I ran into the odd real bug.
The first one I ran into was to do with the 'PutBucketLogging' action; My real unit test case would work with no problem but as I transferred this real world unit test into canned test cases I got a fail on some of the composed XML.
The test parameters for the request where
---
Bucket: oneoffpaws
BucketLoggingStatus:
LoggingEnabled:
TargetBucket: MyTargetBucket
TargetPrefix: mylog
TargetGrants:
- Grantee:
Type: CanonicalUser
DisplayName: OwnerDisplayName
ID: 852b113e7a2f25102679df27bb0ae12b3f85be6BucketOwnerCanonicalUserID
Permission: FULL_CONTROL
and I after processing I was getting this XML
<BucketLoggingStatus xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <LoggingEnabled> <TargetGrants> <TargetBucket>MyTargetBucket</TargetBucket> <Grant> <Grantee> …
but what I should have is;
<BucketLoggingStatus xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <LoggingEnabled> <TargetBucket>string</TargetBucket> <TargetGrants> <Grant> <Grantee>
So that '<TargetBucket>' tag is in the wrong place. I checked the boto;
"LoggingEnabled":{
"type":"structure",
"required":[
"TargetBucket",
"TargetPrefix"
],
"members":{
"TargetBucket":{
"shape":"TargetBucket",
...
},
"TargetGrants":{
"shape":"TargetGrants",
"documentation":"<p/>"
},
"TargetPrefix":{
"shape":"TargetPrefix",
...
}
},
and that was fine and I even checked the source boto and it was the same so it must be in PAWS someplace.
I checked the generated class;
package Paws::S3::LoggingEnabled;
use Moose;
has TargetBucket => (is => 'ro', isa => 'Str', required => 1);
has TargetGrants => (is => 'ro', isa => 'ArrayRef[Paws::S3::TargetGrant]',
request_name => 'Grant',
list_request_name => 'TargetGrants',
traits => ['NameInRequest','ListNameInRequest']);
has TargetPrefix => (is => 'ro', isa => 'Str', required => 1);
1;
and that looks ok. So it must be in the changes I have made in RestXmlCaller.pm.
Poking about in the changes I had made I found that is patch fix this up;
if ($attribute->does('ListNameInRequest')) {
my $location = $attribute->request_name();
my $list_name = $attribute->list_request_name();
-- $xml .= ( join '', map { sprintf '<%s%s>%s</%s>',$location, $self->_to_xml_attributes($attribute->get_value($_)), $self->_to_xml($_), $location } @{ $attribute->get_value($value) } );
-- $xml ="<$list_name>$xml</$list_name>"
++ my $temp_xml = ( join '', map { sprintf '<%s%s>%s</%s>',$location, $self->_to_xml_attributes($attribute->get_value($_)), $self->_to_xml($_), $location } @{ $attribute->get_value($value) } );
++ $temp_xml ="<$list_name>$temp_xml</$list_name>"
if ( $location ne $list_name);
$xml.=$temp_xml;
All I do now is load my XML in a temp var and then wrap that temp if I need to.
After a few more test case I ran into another bug in my RestXmlCaller.pm code. I was getting this
MyContentMD5 <Delete xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <Object> <Key>MyObjectKey</Key> <VersionId>MyObjectVersionId</VersionId> </Object> <Object> <Key>MyObjectKey1</Key> <VersionId>MyObjectVersionId1</VersionId> </Object> <Quiet>1</Quiet> </Delete>
Somehow that 'MyContentMD5' string is getting into my output XML.
Eventually after adding in many many lines of debugging and mucking up each of the the '<' of the tags with a number that I could trace them back I found that there was an edge case where there was a final fall though condition when processing that happens when the 'MyContentMD5' attribute is processed.
The fix was simple enough;
}
-- else {
-- $xml .= $attribute_value;
-- }
}
Just eliminate the fall though condition.
I then carried on with creating more tests, which has got to be one of the more boring of coding operations creating test cases from actual requests. Not going to put the four or fives days of work here as all I would do is turn everyone off coding.
The great thing is that my t/09_request.t actually found two bugs that where present in the code but I had never hit them with my real world unit tests.
Proves that even test cases using mocked data hitting nothing are still are useful.
Leave a comment