private function _testPatchExistingObjectWithOldVersionProperty($objectType) { $objectTypePlural = API::getPluralObjectType($objectType); $key = API::createDataObject($objectType, 'key'); $json = API::createUnsavedDataObject($objectType); $json['version'] = 1; $response = API::userPatch(self::$config['userID'], "{$objectTypePlural}/{$key}", json_encode($json), ["Content-Type: application/json"]); $this->assert412($response); }
/** * @depends testGetFile */ public function testAddFilePartial($getFileData) { // Get serverDateModified $response = API::userGet( self::$config['userID'], "items/{$getFileData['key']}" ); $json = API::getJSONFromResponse($response)['data']; $serverDateModified = $json['dateModified']; sleep(1); $originalVersion = $json['version']; // Get a sync timestamp from before the file is updated require_once 'include/sync.inc.php'; $sessionID = Sync::login(); $xml = Sync::updated($sessionID); $lastsync = (int) $xml['timestamp']; Sync::logout($sessionID); $oldFilename = "work/old"; $fileContents = $getFileData['response']->getBody(); file_put_contents($oldFilename, $fileContents); $newFilename = "work/new"; $patchFilename = "work/patch"; $algorithms = array( "bsdiff" => "bsdiff " . escapeshellarg($oldFilename) . " " . escapeshellarg($newFilename) . " " . escapeshellarg($patchFilename), "xdelta" => "xdelta3 -f -e -9 -S djw -s " . escapeshellarg($oldFilename) . " " . escapeshellarg($newFilename) . " " . escapeshellarg($patchFilename), "vcdiff" => "vcdiff encode " . "-dictionary " . escapeshellarg($oldFilename) . " " . " -target " . escapeshellarg($newFilename) . " " . " -delta " . escapeshellarg($patchFilename) ); foreach ($algorithms as $algo => $cmd) { clearstatcache(); // Create random contents file_put_contents($newFilename, uniqid(self::getRandomUnicodeString(), true)); $newHash = md5_file($newFilename); // Get upload authorization $fileParams = array( "md5" => $newHash, "filename" => "test_" . $fileContents, "filesize" => filesize($newFilename), "mtime" => filemtime($newFilename) * 1000, "contentType" => "text/plain", "charset" => "utf-8" ); $response = API::userPost( self::$config['userID'], "items/{$getFileData['key']}/file", $this->implodeParams($fileParams), array( "Content-Type: application/x-www-form-urlencoded", "If-Match: " . md5_file($oldFilename) ) ); $this->assert200($response); $json = json_decode($response->getBody()); $this->assertNotNull($json); exec($cmd, $output, $ret); if ($ret != 0) { echo "Warning: Error running $algo -- skipping file upload test\n"; continue; } $patch = file_get_contents($patchFilename); $this->assertNotEquals("", $patch); self::$toDelete[] = "$newHash"; // Upload patch file $response = API::userPatch( self::$config['userID'], "items/{$getFileData['key']}/file?algorithm=$algo&upload=" . $json->uploadKey, $patch, array( "If-Match: " . md5_file($oldFilename) ) ); $this->assert204($response); unlink($patchFilename); rename($newFilename, $oldFilename); // Verify attachment item metadata $response = API::userGet( self::$config['userID'], "items/{$getFileData['key']}" ); $json = API::getJSONFromResponse($response)['data']; $this->assertEquals($fileParams['md5'], $json['md5']); $this->assertEquals($fileParams['mtime'], $json['mtime']); $this->assertEquals($fileParams['contentType'], $json['contentType']); $this->assertEquals($fileParams['charset'], $json['charset']); // Make sure version has changed $this->assertNotEquals($originalVersion, $json['version']); // Make sure new attachment is passed via sync $sessionID = Sync::login(); $xml = Sync::updated($sessionID, $lastsync); Sync::logout($sessionID); $this->assertGreaterThan(0, $xml->updated[0]->count()); // Verify file on S3 $response = API::userGet( self::$config['userID'], "items/{$getFileData['key']}/file" ); $this->assert302($response); $location = $response->getHeader("Location"); $response = HTTP::get($location); $this->assert200($response); $this->assertEquals($fileParams['md5'], md5($response->getBody())); $t = $fileParams['contentType']; $this->assertEquals( $t . (($t && $fileParams['charset']) ? "; charset={$fileParams['charset']}" : ""), $response->getHeader("Content-Type") ); } }
public function testParentItemPatch() { $json = API::createItem("book", false, $this, 'jsonData'); $parentKey = $json['key']; $parentVersion = $json['version']; $json = API::createAttachmentItem("linked_url", [], $parentKey, $this, 'jsonData'); $childKey = $json['key']; $childVersion = $json['version']; $this->assertArrayHasKey('parentItem', $json); $this->assertEquals($parentKey, $json['parentItem']); $json = array( 'title' => 'Test' ); // With PATCH, parent shouldn't be removed even though unspecified $response = API::userPatch( self::$config['userID'], "items/$childKey", json_encode($json), array("If-Unmodified-Since-Version: " . $childVersion) ); $this->assert204($response); $json = API::getItem($childKey, $this, 'json')['data']; $this->assertArrayHasKey('parentItem', $json); $childVersion = $json['version']; // But it should be removed with parentItem: false $json = [ 'parentItem' => false ]; $response = API::userPatch( self::$config['userID'], "items/$childKey", json_encode($json), ["If-Unmodified-Since-Version: " . $childVersion] ); $this->assert204($response); $json = API::getItem($childKey, $this, 'json')['data']; $this->assertArrayNotHasKey('parentItem', $json); }
public function testCollectionItemChange() { $collectionKey1 = API::createCollection('Test', false, $this, 'key'); $collectionKey2 = API::createCollection('Test', false, $this, 'key'); $json = API::createItem("book", array('collections' => array($collectionKey1)), $this, 'json'); $itemKey1 = $json['key']; $itemVersion1 = $json['version']; $this->assertEquals([$collectionKey1], $json['data']['collections']); $json = API::createItem("journalArticle", array('collections' => array($collectionKey2)), $this, 'json'); $itemKey2 = $json['key']; $itemVersion2 = $json['version']; $this->assertEquals([$collectionKey2], $json['data']['collections']); $json = API::getCollection($collectionKey1, $this); $this->assertEquals(1, $json['meta']['numItems']); $json = API::getCollection($collectionKey2, $this); $this->assertEquals(1, $json['meta']['numItems']); $collectionData2 = $json['data']; $libraryVersion = API::getLibraryVersion(); // Add items to collection $response = API::userPatch(self::$config['userID'], "items/{$itemKey1}", json_encode(array("collections" => array($collectionKey1, $collectionKey2))), array("Content-Type: application/json", "If-Unmodified-Since-Version: {$itemVersion1}")); $this->assert204($response); // Item version should change $json = API::getItem($itemKey1, $this); $this->assertEquals($libraryVersion + 1, $json['version']); // Collection timestamp shouldn't change, but numItems should $json = API::getCollection($collectionKey2, $this); $this->assertEquals(2, $json['meta']['numItems']); $this->assertEquals($collectionData2['version'], $json['version']); $collectionData2 = $json['data']; $libraryVersion = API::getLibraryVersion(); // Remove collections $response = API::userPatch(self::$config['userID'], "items/{$itemKey2}", json_encode(array("collections" => array())), array("Content-Type: application/json", "If-Unmodified-Since-Version: {$itemVersion2}")); $this->assert204($response); // Item version should change $json = API::getItem($itemKey2, $this); $this->assertEquals($libraryVersion + 1, $json['version']); // Collection timestamp shouldn't change, but numItems should $json = API::getCollection($collectionKey2, $this); $this->assertEquals(1, $json['meta']['numItems']); $this->assertEquals($collectionData2['version'], $json['version']); // Check collections arrays and numItems $json = API::getItem($itemKey1, $this); $this->assertCount(2, $json['data']['collections']); $this->assertContains($collectionKey1, $json['data']['collections']); $this->assertContains($collectionKey2, $json['data']['collections']); $json = API::getItem($itemKey2, $this); $this->assertCount(0, $json['data']['collections']); $json = API::getCollection($collectionKey1, $this); $this->assertEquals(1, $json['meta']['numItems']); $json = API::getCollection($collectionKey2, $this); $this->assertEquals(1, $json['meta']['numItems']); }