Paws XIV (The Sun King)

Well carrying on with my quest to clean up the Paws S3 code I decided while I am waiting for my last batch of changes to be reviewed I decided to review some of the 'TODO' tests.

TODO passed: 6364, 6370, 7896, 10045, 10052, 10137

First a 'TODO' test is a stubbed in test that will most likely fail and if it does it will not effect the final Pass/Fail of test case. It is basically one of these

The first one I am going to play with is 's3-get-bucket-location.response.test.yml which looks like this

--- todo: 'S3 is not stable' call: GetBucketLocation service: S3 tests: - expected: EU op: eq path: LocationConstraint

So the first thing I did was chop off that 'todo' line;

--- --todo: 'S3 is not stable' call: GetBucketLocation service: S3 …

and then check the content in the '3-get-bucket-location.response';

--- content: | <?xml version="1.0" encoding="UTF-8"?> <LocationConstraint xmlns="">EU</LocationConstraint> headers: [] status: 200

and that looks ok and on a test run I get the fail

ok 10045 - Call S3->GetBucketLocation from t/10_responses/s3-get-bucket-location.response Use of uninitialized value $got in string eq at (eval in cmp_ok) t/10_responses.t line 136. not ok 10046 - Got LocationConstraint eq EU from result

# Failed test 'Got LocationConstraint eq EU from result'
# at t/10_responses.t line 136.
# got: undef
# expected: 'EU'

and one less on my todo pass

TODO passed: 6364, 6370, 7896, 10052, 10137

Looking to see where things have gone awry I had a look at the generated 'Paws::S3::GetBucketLocationOutput' class;

package Paws::S3::GetBucketLocationOutput;
  use Moose;
  has LocationConstraint => (is => 'ro', isa => 'Str');

has _request_id => (is => 'ro', isa => 'Str');

and that links up with the test, so I think botocore it correct it must be in the 'Paws::Net::RestXMLResponse' class someplace

I know I am getting the correct response as I did a Dump of that in the 'process' sub and got;

process response=$VAR1 = bless( {
                 'headers' => {},
                 'content' => '<?xml version="1.0" encoding="UTF-8"?>
<LocationConstraint xmlns="">EU</LocationConstraint>
                 'status' => '200'
               }, 'Paws::Net::APIResponse' );

and I will have to look a little deeper and I should look in the 'unserialize_response' sub as that is where the XML is converted into a hash and what I am going to look at is what goes in there;

 sub unserialize_response {
    my ($self, $data) = @_;
   warn(“XML in=”.Dumper($data));
 return {} if (not defined $data or $data eq '');

my $xml = XML::Simple->new(
ForceArray => qr/^(?:item|Errors)/i,
KeyAttr => '',
SuppressEmpty => undef,
return $xml->parse_string($data);

and I get

XML in=$VAR1 = '<?xml version="1.0" encoding="UTF-8"?>
<LocationConstraint xmlns="">EU</LocationConstraint>';

so the data are coming in correctly could it be the parser not working?

 } else {
        $unserialized_struct = eval { $self->unserialize_response( $content ) };
++        warn("JPS response_to_object unserialized_struct=".Dumper($unserialized_struct));
        if ($@){

and I get

response_to_object unserialized_struct=$VAR1 = {
          'xmlns' => '',
          'content' => 'EU'

hmm correct but there is no way that can be linked back to the 'LocationConstraint' attribute in my generated class. I think I will have to wrap it somehow or parse it in another way as I want to see in

 'content' => {<LocationConstraint>'EU'</LocationConstraint>},

I am not an expert of XML::Simple but I think if I do this

my $xml = XML::Simple->new(
      ForceArray    => qr/^(?:item|Errors)/i,
      SuppressEmpty => undef,
      ForceContent => 1,
      ContentKey => 'LocationConstraint',
      KeyAttr => ''

Add in the ' ForceContent => 1' and 'ContentKey => 'LocationConstraint' options to the parser and it will work but that will kill any other XML parseing as it wants the tag defined byt that ' ContentKey' option otherwise the parse will fail.

Looks like I have to figure out some way to get a flag in there to help me out? Perhaps a new trait?

Lets have a look in the botocore json to see what I can work with, in this case I want to look at is the '"GetBucketLocationOutput" stuct


Hmm that does not look correct as it is taking a shape as a ' BucketLocationConstraint' which to me means it trying to limit some input not output? Anyway that constraint looks like this;


I could just change the ' LocationConstraint' but I do not want to change the boto code more that I have to, so there must be a better way?

Anyway I can see why the left this one out.


Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations