
multiple API verstions for each service. This included updating the directory structure for the tests and moving the Common files to a Common namespace. Implements blueprint multiple-api-versions Change-Id: I9f9dfc4ef8f4172243519772a9af86dd92690fcf
446 lines
13 KiB
PHP
446 lines
13 KiB
PHP
<?php
|
|
/* ============================================================================
|
|
(c) Copyright 2012-2014 Hewlett-Packard Development Company, L.P.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
============================================================================ */
|
|
/**
|
|
* Unit tests for Containers.
|
|
*/
|
|
namespace OpenStack\Tests\ObjectStore\v1\Resource;
|
|
|
|
use \OpenStack\ObjectStore\v1\Resource\Container;
|
|
use \OpenStack\ObjectStore\v1\Resource\Object;
|
|
use \OpenStack\ObjectStore\v1\Resource\ACL;
|
|
|
|
class ContainerTest extends \OpenStack\Tests\TestCase
|
|
{
|
|
const FILENAME = 'unit-test-dummy.txt';
|
|
const FILESTR = 'This is a test.';
|
|
|
|
// The factory functions (newFrom*) are tested in the
|
|
// ObjectStorage tests, as they are required there.
|
|
// Rather than build a Mock to achieve the same test here,
|
|
// we just don't test them again.
|
|
|
|
public function testConstructor()
|
|
{
|
|
$container = new Container('foo');
|
|
$this->assertEquals('foo', $container->name());
|
|
|
|
// These will now cause the system to try to fetch a remote
|
|
// container.
|
|
//$this->assertEquals(0, $container->bytes());
|
|
//$this->assertEquals(0, $container->count());
|
|
}
|
|
|
|
/**
|
|
* @expectedException \OpenStack\Common\Exception
|
|
*/
|
|
public function testConstructorFailure()
|
|
{
|
|
$container = new Container('foo');
|
|
$this->assertEquals('foo', $container->name());
|
|
|
|
// These will now cause the system to try to fetch a remote
|
|
// container. This is a failure condition.
|
|
$this->assertEquals(0, $container->bytes());
|
|
}
|
|
|
|
public function testCountable()
|
|
{
|
|
// Verify that the interface Countable is properly
|
|
// implemented.
|
|
|
|
$mockJSON = array('count' => 5, 'bytes' => 128, 'name' => 'foo');
|
|
|
|
$container = Container::newFromJSON($mockJSON, 'fake', 'fake');
|
|
|
|
$this->assertEquals(5, count($container));
|
|
|
|
}
|
|
|
|
const FNAME = 'testSave';
|
|
const FCONTENT = 'This is a test.';
|
|
const FTYPE = 'application/x-monkey-file';
|
|
|
|
public function testSave()
|
|
{
|
|
// Clean up anything left.
|
|
$this->destroyContainerFixture();
|
|
|
|
$container = $this->containerFixture();
|
|
|
|
$obj = new Object(self::FNAME, self::FCONTENT, self::FTYPE);
|
|
$obj->setMetadata(array('foo' => '1234'));
|
|
|
|
$this->assertEquals(self::FCONTENT, $obj->content());
|
|
|
|
try {
|
|
$ret = $container->save($obj);
|
|
} catch (\Exception $e) {
|
|
$this->destroyContainerFixture();
|
|
throw $e;
|
|
}
|
|
|
|
$this->assertTrue($ret);
|
|
}
|
|
|
|
/**
|
|
* @depends testSave
|
|
*/
|
|
public function testRemoteObject()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$object = $container->remoteObject(self::FNAME);
|
|
|
|
$this->assertEquals(self::FNAME, $object->name());
|
|
$this->assertEquals(self::FTYPE, $object->contentType());
|
|
|
|
$etag = md5(self::FCONTENT);
|
|
$this->assertEquals($etag, $object->eTag());
|
|
|
|
$md = $object->metadata();
|
|
$this->assertEquals(1, count($md));
|
|
|
|
// Note that headers are normalized remotely to have initial
|
|
// caps. Since we have no way of knowing what the original
|
|
// metadata casing is, we leave it with initial caps.
|
|
$this->assertEquals('1234', $md['Foo']);
|
|
|
|
$content = $object->content();
|
|
$this->assertEquals(self::FCONTENT, $content);
|
|
|
|
// Make sure I can do this twice (regression).
|
|
// Note that this SHOULD perform another request.
|
|
$this->assertEquals(self::FCONTENT, $object->content());
|
|
|
|
// Overwrite the copy:
|
|
$object->setContent('HI');
|
|
$this->assertEquals('HI', $object->content());
|
|
|
|
// Make sure I can do this twice (regression check).
|
|
$this->assertEquals('HI', $object->content());
|
|
}
|
|
|
|
|
|
/**
|
|
* @depends testRemoteObject
|
|
*/
|
|
public function testRefresh()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$object = $container->remoteObject(self::FNAME);
|
|
|
|
$content = (string) $object->content();
|
|
$object->setContent('FOO');
|
|
$this->assertEquals('FOO', $object->content());
|
|
|
|
$object->refresh(true);
|
|
$this->assertEquals($content, (string) $object->content());
|
|
|
|
$object->refresh(false);
|
|
$this->assertEquals($content, (string) $object->content());
|
|
|
|
}
|
|
|
|
/**
|
|
* @depends testRemoteObject
|
|
*/
|
|
public function testObject()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$object = $container->object(self::FNAME);
|
|
|
|
$this->assertEquals(self::FNAME, $object->name());
|
|
$this->assertEquals(self::FTYPE, $object->contentType());
|
|
|
|
$etag = md5(self::FCONTENT);
|
|
$this->assertEquals($etag, $object->eTag());
|
|
|
|
$md = $object->metadata();
|
|
$this->assertEquals(1, count($md));
|
|
|
|
// Note that headers are normalized remotely to have initial
|
|
// caps. Since we have no way of knowing what the original
|
|
// metadata casing is, we leave it with initial caps.
|
|
$this->assertEquals('1234', $md['Foo']);
|
|
|
|
$content = $object->content();
|
|
|
|
$this->assertEquals(self::FCONTENT, $content);
|
|
|
|
// Overwrite the copy:
|
|
$object->setContent('HI');
|
|
$this->assertEquals('HI', $object->content());
|
|
|
|
// Make sure this throws a 404.
|
|
try {
|
|
$foo = $container->object('no/such');
|
|
} catch (\OpenStack\Common\Exception $e) {
|
|
$this->assertInstanceOf('\OpenStack\Common\Transport\Exception\FileNotFoundException', $e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @depends testSave
|
|
*/
|
|
public function testObjects()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$obj1 = new Object('a/' . self::FNAME, self::FCONTENT, self::FTYPE);
|
|
$obj2 = new Object('a/b/' . self::FNAME, self::FCONTENT, self::FTYPE);
|
|
|
|
$container->save($obj1);
|
|
$container->save($obj2);
|
|
|
|
// Now we have a container with three items.
|
|
$objects = $container->objects();
|
|
|
|
$this->assertEquals(3, count($objects));
|
|
|
|
$objects = $container->objects(1, 'a/' . self::FNAME);
|
|
|
|
$this->assertEquals(1, count($objects));
|
|
}
|
|
|
|
/**
|
|
* @depends testObjects
|
|
*/
|
|
public function testGetIterator()
|
|
{
|
|
$container = $this->containerFixture();
|
|
|
|
$it = $container->getIterator();
|
|
$this->assertInstanceOf('Traversable', $it);
|
|
|
|
$i = 0;
|
|
foreach ($container as $item) {
|
|
++$i;
|
|
}
|
|
$this->assertEquals(3, $i);
|
|
|
|
}
|
|
|
|
/**
|
|
* @depends testObjects
|
|
*/
|
|
public function testObjectsWithPrefix()
|
|
{
|
|
$container = $this->containerFixture();
|
|
|
|
$objects = $container->objectsWithPrefix('a/');
|
|
$this->assertEquals(2, count($objects));
|
|
|
|
foreach ($objects as $o) {
|
|
if ($o instanceof Object) {
|
|
$this->assertEquals('a/' . self::FNAME, $o->name());
|
|
} else {
|
|
$this->assertEquals('a/b/', $o->path());
|
|
}
|
|
|
|
}
|
|
|
|
// Since we set the delimiter to ':' we will get back
|
|
// all of the objects in a/. This is because none of
|
|
// the objects contain ':' in their names.
|
|
$objects = $container->objectsWithPrefix('a/', ':');
|
|
$this->assertEquals(2, count($objects));
|
|
|
|
foreach ($objects as $o) {
|
|
$this->assertInstanceOf('\OpenStack\ObjectStore\v1\Resource\Object', $o);
|
|
}
|
|
|
|
// This should give us one file and one subdir.
|
|
$objects = $container->objectsWithPrefix('', '/');
|
|
$this->assertEquals(2, count($objects));
|
|
|
|
foreach ($objects as $o) {
|
|
if ($o instanceof Object) {
|
|
$this->assertEquals(self::FNAME, $o->name());
|
|
} else {
|
|
$this->assertEquals('a/', $o->path());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @depends testObjects
|
|
*/
|
|
public function testObjectsWithPath()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$objects = $container->objectsByPath('a/b/');
|
|
|
|
$this->assertEquals(1, count($objects));
|
|
|
|
$o = array_shift($objects);
|
|
$this->assertEquals('a/b/' . self::FNAME, $o->name());
|
|
|
|
/*
|
|
* The Open Stack documentation is unclear about how best to
|
|
* use paths. Experimentation suggests that if you rely on paths
|
|
* instead of prefixes, your best bet is to create directory
|
|
* markers.
|
|
*/
|
|
|
|
// Test subdir listings:
|
|
// This does not work (by design?) with Path. You have to use prefix
|
|
// or else create directory markers.
|
|
// $obj1 = new Object('a/aa/aaa/' . self::FNAME, self::FCONTENT, self::FTYPE);
|
|
// $container->save($obj1);
|
|
// $objects = $container->objectsByPath('a/aaa', '/');
|
|
|
|
// $this->assertEquals(1, count($objects), 'One subdir');
|
|
|
|
// $objects = $container->objectsByPath('a/');
|
|
// throw new \Exception(print_r($objects, true));
|
|
// $this->assertEquals(2, count($objects));
|
|
|
|
// foreach ($objects as $o) {
|
|
// if ($o instanceof Object) {
|
|
// $this->assertEquals('a/' . self::FNAME, $o->name());
|
|
// }
|
|
// else {
|
|
// $this->assertEquals('a/b/', $o->path());
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* @depends testRemoteObject
|
|
*/
|
|
public function testUpdateMetadata()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$object = $container->remoteObject(self::FNAME);
|
|
|
|
$md = $object->metadata();
|
|
|
|
$this->assertEquals('1234', $md['Foo']);
|
|
|
|
$md['Foo'] = 456;
|
|
$md['Bar'] = 'bert';
|
|
$object->setMetadata($md);
|
|
|
|
$container->updateMetadata($object);
|
|
|
|
$copy = $container->remoteObject(self::FNAME);
|
|
|
|
$this->assertEquals('456', $md['Foo']);
|
|
$this->assertEquals('bert', $md['Bar']);
|
|
|
|
// Now we need to canary test:
|
|
$this->assertEquals($object->contentType(), $copy->contentType());
|
|
$this->assertEquals($object->contentLength(), $copy->contentLength());
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* @depends testRemoteObject
|
|
*/
|
|
public function testCopy()
|
|
{
|
|
$container = $this->containerFixture();
|
|
$object = $container->remoteObject(self::FNAME);
|
|
|
|
$container->copy($object, 'FOO-1.txt');
|
|
|
|
$copy = $container->remoteObject('FOO-1.txt');
|
|
|
|
$this->assertEquals($object->contentType(), $copy->contentType());
|
|
$this->assertEquals($object->etag(), $copy->etag());
|
|
|
|
$container->delete('foo-1.txt');
|
|
|
|
}
|
|
|
|
/**
|
|
* @depends testCopy
|
|
*/
|
|
public function testCopyAcrossContainers()
|
|
{
|
|
// Create a new container.
|
|
$store = $this->objectStore();
|
|
$cname = self::$settings['openstack.swift.container'] . 'COPY';
|
|
if ($store->hasContainer($cname)) {
|
|
$this->eradicateContainer($cname);
|
|
}
|
|
|
|
$store->createContainer($cname);
|
|
$newContainer = $store->container($cname);
|
|
|
|
// Get teh old container and its object.
|
|
$container = $this->containerFixture();
|
|
$object = $container->remoteObject(self::FNAME);
|
|
|
|
$ret = $container->copy($object, 'foo-1.txt', $cname);
|
|
|
|
$this->assertTrue($ret);
|
|
|
|
$copy = $newContainer->remoteObject('foo-1.txt');
|
|
|
|
$this->assertEquals($object->etag(), $copy->etag());
|
|
|
|
$this->eradicateContainer($cname);
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @depends testSave
|
|
*/
|
|
public function testDelete()
|
|
{
|
|
$container = $this->containerFixture();
|
|
|
|
$ret = $container->delete(self::FNAME);
|
|
|
|
$fail = $container->delete('no_such_file.txt');
|
|
|
|
$this->destroyContainerFixture();
|
|
$this->assertTrue($ret);
|
|
$this->assertFalse($fail);
|
|
|
|
}
|
|
|
|
/**
|
|
* @group public
|
|
*/
|
|
public function testAcl()
|
|
{
|
|
$store = $this->objectStore();
|
|
$cname = self::$settings['openstack.swift.container'] . 'PUBLIC';
|
|
|
|
if ($store->hasContainer($cname)) {
|
|
$store->deleteContainer($cname);
|
|
}
|
|
|
|
$store->createContainer($cname, ACL::makePublic());
|
|
|
|
|
|
$store->containers();
|
|
$container = $store->container($cname);
|
|
|
|
$acl = $container->acl();
|
|
|
|
$this->assertInstanceOf('\OpenStack\ObjectStore\v1\Resource\ACL', $acl);
|
|
$this->assertTrue($acl->isPublic());
|
|
|
|
$store->deleteContainer($cname);
|
|
|
|
}
|
|
|
|
}
|