Repository: qdrant/qdrant
File: tests/e2e_tests/test_snapshots_recovery.py (Python)

Code before:
        config_file = self.create_config_with_storage(storage_method, tmp_path)
        
        config = QdrantContainerConfig(
            network_mode="host",
            volumes={
                str(config_file): {
                    'bind': '/qdrant/config/config.yaml',
                    'mode': 'ro'
                }
            }
        )
        container_info = qdrant_container_factory(config)
        
        client = ClientUtils(host=container_info.host, port=container_info.http_port)
        
        # Create collection and insert points
        collection_config = {"vectors": {"size": 4, "distance": "Dot"}}
        client.create_collection("test_collection", collection_config)
        for points_batch in client.generate_points(2):
            client.insert_points("test_collection", points_batch)

        # Create collection snapshot
        snapshot_name = client.create_snapshot("test_collection")
        assert snapshot_name, "Snapshot creation failed"
        
        # Download snapshot
        snapshot_content, snapshot_checksum = client.download_snapshot("test_collection", snapshot_name)
        assert len(snapshot_content) > 0, "Downloaded snapshot is empty"
        
        # Save snapshot to file for later use
        snapshot_file = tmp_path / "test_collection.snapshot"
        with open(snapshot_file, 'wb') as f:
            f.write(snapshot_content)
        
        # Test 1: Recover from URL
        snapshot_url = f"http://{client.host}:{client.port}/collections/test_collection/snapshots/{snapshot_name}"
        client.recover_snapshot_from_url("test_collection_recovered_1", snapshot_url, snapshot_checksum)
        
        # Verify recovered collection exists
        client.verify_collection_exists("test_collection_recovered_1")
        
        # Test 2: Upload snapshot as file
        client.upload_snapshot_file("test_collection_recovered_2", snapshot_content)
        
        # Verify second recovered collection exists
        client.verify_collection_exists("test_collection_recovered_2")
        
        # Test shard snapshots
        # Create shard snapshot
        shard_snapshot_name = client.create_shard_snapshot("test_collection", 0)
        assert shard_snapshot_name, "Shard snapshot creation failed"

Review comment (bug):
```py
def create_snapshot(self, collection_name: str = "test_collection") -> str:
        """Create a snapshot of the collection."""
        snapshot_info = self.client.create_snapshot(collection_name=collection_name)
        return snapshot_info.name
```

The code needs to be adjusted to return `None` or it will raise exception that property doesn't exist which still fails the test but is wrong from the API point of view.

Something like

```py
def create_snapshot(self, collection_name: str = "test_collection") -> Optional[str]:
        """Create a snapshot of the collection."""
        snapshot_info = self.client.create_snapshot(collection_name=collection_name)
        return snapshot_info.name if snapshot_info else None
```


Code after:
        config_file = self.create_config_with_storage(storage_method, tmp_path)
        
        config = QdrantContainerConfig(
            network_mode="host",
            volumes={
                str(config_file): {
                    'bind': '/qdrant/config/config.yaml',
                    'mode': 'ro'
                }
            }
        )
        container_info = qdrant_container_factory(config)
        
        client = ClientUtils(host=container_info.host, port=container_info.http_port)
        client.wait_for_server()
        
        # Create collection and insert points
        collection_config = {"vectors": {"size": 4, "distance": "Dot"}}
        client.create_collection("test_collection", collection_config)
        for points_batch in client.generate_points(2):
            client.insert_points("test_collection", points_batch, wait=True)
        initial_collection_config = client.get_collection_info_dict("test_collection")["result"]["config"]

        # Create collection snapshot
        snapshot_name = client.create_snapshot("test_collection")
        assert snapshot_name, "Snapshot creation failed"
        
        # Download snapshot
        snapshot_content, snapshot_checksum = client.download_snapshot("test_collection", snapshot_name)
        assert len(snapshot_content) > 0, "Downloaded snapshot is empty"
        
        # Save snapshot to file for later use
        snapshot_file = tmp_path / "test_collection.snapshot"
        with open(snapshot_file, 'wb') as f:
            f.write(snapshot_content)
        
        # Test 1: Recover from URL
        snapshot_url = f"http://{client.host}:{client.port}/collections/test_collection/snapshots/{snapshot_name}"
        client.recover_snapshot_from_url("test_collection_recovered_1", snapshot_url, snapshot_checksum)
        
        # Verify recovered collection exists
        resp = client.verify_collection_exists("test_collection_recovered_1")
        assert resp["result"].get("points_count") == 200, "Recovered collection does not have expected number of points"
        assert resp["result"].get("config") == initial_collection_config, "Recovered collection config does not match"

        # Test 2: Upload snapshot as file
        client.upload_snapshot_file("test_collection_recovered_2", snapshot_content)
        
        # Verify second recovered collection exists
        client.verify_collection_exists("test_collection_recovered_2")