Skip to content

Commit 2de0e17

Browse files
authored
Integration test for MultiPartUpload. (#459)
Adding two tests with mocked fetch. Tests run uploading for Blob V1 and Blob V2 and checks if the count of the requests are as expected. Resolves: OLPEDGE-2538 Relates-To: OLPEDGE-2456 Signed-off-by: Oleksii Zubko <[email protected]>
1 parent 55ce786 commit 2de0e17

File tree

1 file changed

+244
-0
lines changed

1 file changed

+244
-0
lines changed
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Copyright (C) 2021 HERE Europe B.V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
import * as chai from "chai";
21+
import sinonChai = require("sinon-chai");
22+
import sinon = require("sinon");
23+
24+
import { MultiPartUploadWrapper } from "@here/olp-sdk-dataservice-write";
25+
import { OlpClientSettings } from "@here/olp-sdk-core";
26+
import { FetchMock } from "../FetchMock";
27+
28+
chai.use(sinonChai);
29+
30+
const assert = chai.assert;
31+
const expect = chai.expect;
32+
33+
describe("Multipart Upload Integration Test", function() {
34+
let fetchMock: FetchMock;
35+
let sandbox: sinon.SinonSandbox;
36+
let fetchStub: sinon.SinonStub;
37+
let settings: OlpClientSettings;
38+
39+
settings = new OlpClientSettings({
40+
environment: "here",
41+
getToken: () => Promise.resolve("mocked-token")
42+
});
43+
const catalogHrn = "hrn:here:data:::mocked-hrn";
44+
const layerId = "mocked-layer-id";
45+
const dataSize = 74 * 1024 * 1024;
46+
const contentType = "text/plain";
47+
const data = Buffer.alloc(dataSize, 1);
48+
49+
const headers = new Headers();
50+
headers.append("cache-control", "max-age=3600");
51+
52+
before(function() {
53+
sandbox = sinon.createSandbox();
54+
});
55+
56+
afterEach(function() {
57+
sandbox.restore();
58+
});
59+
60+
beforeEach(function() {
61+
fetchMock = new FetchMock();
62+
fetchStub = sandbox.stub(global as any, "fetch");
63+
fetchStub.callsFake(fetchMock.fetch());
64+
65+
settings = new OlpClientSettings({
66+
environment: "here",
67+
getToken: () => Promise.resolve("mocked-token")
68+
});
69+
});
70+
71+
it("Should initialize", function() {
72+
const wrapper = new MultiPartUploadWrapper(
73+
{
74+
catalogHrn,
75+
layerId,
76+
handle: "mocked-dataHandle",
77+
blobVersion: "v1",
78+
contentType
79+
},
80+
settings
81+
);
82+
83+
assert.isDefined(wrapper);
84+
expect(wrapper).be.instanceOf(MultiPartUploadWrapper);
85+
});
86+
87+
it("Should upload to Blob V1", async function() {
88+
const mockedResponses = new Map();
89+
90+
mockedResponses.set(
91+
`https://api-lookup.data.api.platform.here.com/lookup/v1/resources/hrn:here:data:::mocked-hrn/apis`,
92+
new Response(
93+
JSON.stringify([
94+
{
95+
api: "blob",
96+
version: "v1",
97+
baseURL: `https://mocked.api/blobstore/v1`,
98+
parameters: {}
99+
}
100+
]),
101+
{ headers }
102+
)
103+
);
104+
105+
mockedResponses.set(
106+
`https://mocked.api/blobstore/v1/layers/mocked-layer-id/data/mocked-dataHandle/multiparts`,
107+
new Response(
108+
JSON.stringify({
109+
links: {
110+
status: {
111+
href: `https://mocked.api/multiparts/mocked-blob-token`,
112+
method: "GET"
113+
},
114+
delete: {
115+
href: `https://mocked.api/multiparts/mocked-blob-token`,
116+
method: "DELETE"
117+
},
118+
uploadPart: {
119+
href: `https://mocked.api/multiparts/mocked-blob-token/parts`,
120+
method: "POST"
121+
},
122+
complete: {
123+
href: `https://mocked.api/multiparts/mocked-blob-token`,
124+
method: "PUT"
125+
}
126+
}
127+
}),
128+
{ headers }
129+
)
130+
);
131+
132+
const partsHeaders = new Headers();
133+
partsHeaders.append("cache-control", "max-age=3600");
134+
partsHeaders.append("ETag", `${Math.random() * 10000}`);
135+
136+
for (let partNumber = 0; partNumber < 16; partNumber++) {
137+
mockedResponses.set(
138+
`https://mocked.api/multiparts/mocked-blob-token/parts?partNumber=${partNumber}`,
139+
new Response(undefined, { headers: partsHeaders })
140+
);
141+
}
142+
143+
mockedResponses.set(
144+
`https://mocked.api/multiparts/mocked-blob-token`,
145+
new Response(undefined, { headers })
146+
);
147+
148+
// Setup the fetch to use mocked responses.
149+
fetchMock.withMockedResponses(mockedResponses);
150+
151+
const wrapper = new MultiPartUploadWrapper(
152+
{
153+
catalogHrn,
154+
layerId,
155+
handle: "mocked-dataHandle",
156+
blobVersion: "v1",
157+
contentType
158+
},
159+
settings
160+
);
161+
162+
await wrapper.upload(data);
163+
164+
/**
165+
* Should be 18 calls:
166+
* 1 - lookup
167+
* 1 - start multipart
168+
* 15 - upload part
169+
* 1 - complete multipart
170+
*/
171+
expect(fetchStub.callCount).to.be.equal(18);
172+
});
173+
174+
it("Should upload to Blob V2", async function() {
175+
const mockedResponses = new Map();
176+
177+
mockedResponses.set(
178+
`https://api-lookup.data.api.platform.here.com/lookup/v1/resources/hrn:here:data:::mocked-hrn/apis`,
179+
new Response(
180+
JSON.stringify([
181+
{
182+
api: "blob",
183+
version: "v2",
184+
baseURL: `https://mocked.api/blobstore/v2`,
185+
parameters: {}
186+
}
187+
]),
188+
{ headers }
189+
)
190+
);
191+
192+
mockedResponses.set(
193+
`https://mocked.api/blobstore/v2/layers/mocked-layer-id/keys/mocked-key`,
194+
new Response(
195+
JSON.stringify({
196+
multipartToken: "mocked-multipartToken"
197+
}),
198+
{ headers }
199+
)
200+
);
201+
202+
for (let partNumber = 0; partNumber < 16; partNumber++) {
203+
mockedResponses.set(
204+
`https://mocked.api/blobstore/v2/layers/mocked-layer-id/keysMultipart/mocked-multipartToken/parts?partNumber=${partNumber}`,
205+
new Response(
206+
JSON.stringify({
207+
id: `${Math.random() * 10000}`
208+
}),
209+
{ headers }
210+
)
211+
);
212+
}
213+
214+
mockedResponses.set(
215+
`https://mocked.api/blobstore/v2/layers/mocked-layer-id/keysMultipart/mocked-multipartToken`,
216+
new Response(undefined, { headers })
217+
);
218+
219+
// Setup the fetch to use mocked responses.
220+
fetchMock.withMockedResponses(mockedResponses);
221+
222+
const wrapper = new MultiPartUploadWrapper(
223+
{
224+
catalogHrn,
225+
layerId,
226+
handle: "mocked-key",
227+
blobVersion: "v2",
228+
contentType
229+
},
230+
settings
231+
);
232+
233+
await wrapper.upload(data);
234+
235+
/**
236+
* Should be 18 calls:
237+
* 1 - lookup
238+
* 1 - start multipart
239+
* 15 - upload part
240+
* 1 - complete multipart
241+
*/
242+
expect(fetchStub.callCount).to.be.equal(18);
243+
});
244+
});

0 commit comments

Comments
 (0)