TEST(ImageResourceTest, MultipartImage) { ResourceFetcher* fetcher = ResourceFetcher::create(nullptr); KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); URLTestHelpers::registerMockedURLLoad(testURL, "cancelTest.html", "text/html"); // Emulate starting a real load, but don't expect any "real" WebURLLoaderClient callbacks. ResourcePtr<ImageResource> cachedImage = new ImageResource(ResourceRequest(testURL), nullptr); cachedImage->setIdentifier(createUniqueIdentifier()); cachedImage->load(fetcher, ResourceLoaderOptions()); Platform::current()->unitTestSupport()->unregisterMockedURL(testURL); MockImageResourceClient client(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->status()); // Send the multipart response. No image or data buffer is created. // Note that the response must be routed through ResourceLoader to // ensure the load is flagged as multipart. ResourceResponse multipartResponse(KURL(), "multipart/x-mixed-replace", 0, nullAtom, String()); cachedImage->loader()->didReceiveResponse(nullptr, WrappedResourceResponse(multipartResponse), nullptr); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client.imageChangedCount(), 0); ASSERT_FALSE(client.notifyFinishedCalled()); // Send the response for the first real part. No image or data buffer is created. const char* svgData = "<svg xmlns='http://www.w3.org/2000/svg' width='1' height='1'><rect width='1' height='1' fill='green'/></svg>"; unsigned svgDataLength = strlen(svgData); ResourceResponse payloadResponse(KURL(), "image/svg+xml", svgDataLength, nullAtom, String()); cachedImage->loader()->didReceiveResponse(nullptr, WrappedResourceResponse(payloadResponse), nullptr); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client.imageChangedCount(), 0); ASSERT_FALSE(client.notifyFinishedCalled()); // The first bytes arrive. The data buffer is created, but no image is created. cachedImage->appendData(svgData, svgDataLength); ASSERT_TRUE(cachedImage->resourceBuffer()); ASSERT_EQ(cachedImage->resourceBuffer()->size(), svgDataLength); ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client.imageChangedCount(), 0); ASSERT_FALSE(client.notifyFinishedCalled()); // This part finishes. The image is created, callbacks are sent, and the data buffer is cleared. cachedImage->finish(); ASSERT_FALSE(cachedImage->resourceBuffer()); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->image()->isNull()); ASSERT_EQ(cachedImage->image()->width(), 1); ASSERT_EQ(cachedImage->image()->height(), 1); ASSERT_EQ(client.imageChangedCount(), 2); ASSERT_TRUE(client.notifyFinishedCalled()); }
TEST(ImageResourceTest, MultipartImage) { ResourceFetcher* fetcher = ResourceFetcher::create(ImageResourceTestMockFetchContext::create()); KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); ScopedRegisteredURL scopedRegisteredURL(testURL); // Emulate starting a real load, but don't expect any "real" // WebURLLoaderClient callbacks. ImageResource* cachedImage = ImageResource::create(ResourceRequest(testURL)); cachedImage->setIdentifier(createUniqueIdentifier()); fetcher->startLoad(cachedImage); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); EXPECT_EQ(Resource::Pending, cachedImage->getStatus()); // Send the multipart response. No image or data buffer is created. Note that // the response must be routed through ResourceLoader to ensure the load is // flagged as multipart. ResourceResponse multipartResponse(KURL(), "multipart/x-mixed-replace", 0, nullAtom, String()); multipartResponse.setMultipartBoundary("boundary", strlen("boundary")); cachedImage->loader()->didReceiveResponse( nullptr, WrappedResourceResponse(multipartResponse), nullptr); EXPECT_FALSE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(0, client->imageChangedCount()); EXPECT_FALSE(client->notifyFinishedCalled()); EXPECT_EQ("multipart/x-mixed-replace", cachedImage->response().mimeType()); const char firstPart[] = "--boundary\n" "Content-Type: image/svg+xml\n\n"; cachedImage->appendData(firstPart, strlen(firstPart)); // Send the response for the first real part. No image or data buffer is // created. EXPECT_FALSE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(0, client->imageChangedCount()); EXPECT_FALSE(client->notifyFinishedCalled()); EXPECT_EQ("image/svg+xml", cachedImage->response().mimeType()); const char secondPart[] = "<svg xmlns='http://www.w3.org/2000/svg' width='1' height='1'><rect " "width='1' height='1' fill='green'/></svg>\n"; // The first bytes arrive. The data buffer is created, but no image is // created. cachedImage->appendData(secondPart, strlen(secondPart)); EXPECT_TRUE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->hasImage()); EXPECT_EQ(0, client->imageChangedCount()); EXPECT_FALSE(client->notifyFinishedCalled()); // Add a client to check an assertion error doesn't happen // (crbug.com/630983). Persistent<MockImageResourceClient> client2 = new MockImageResourceClient(cachedImage); EXPECT_EQ(0, client2->imageChangedCount()); EXPECT_FALSE(client2->notifyFinishedCalled()); const char thirdPart[] = "--boundary"; cachedImage->appendData(thirdPart, strlen(thirdPart)); ASSERT_TRUE(cachedImage->resourceBuffer()); EXPECT_EQ(strlen(secondPart) - 1, cachedImage->resourceBuffer()->size()); // This part finishes. The image is created, callbacks are sent, and the data // buffer is cleared. cachedImage->loader()->didFinishLoading(nullptr, 0.0, 0); EXPECT_TRUE(cachedImage->resourceBuffer()); EXPECT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); EXPECT_FALSE(cachedImage->getImage()->isNull()); EXPECT_EQ(1, cachedImage->getImage()->width()); EXPECT_EQ(1, cachedImage->getImage()->height()); EXPECT_EQ(1, client->imageChangedCount()); EXPECT_TRUE(client->notifyFinishedCalled()); EXPECT_EQ(1, client2->imageChangedCount()); EXPECT_TRUE(client2->notifyFinishedCalled()); }