You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1081 lines
18 KiB
JavaScript

import { loadKTX } from "../../Source/Cesium.js";
import { PixelFormat } from "../../Source/Cesium.js";
import { Request } from "../../Source/Cesium.js";
import { RequestErrorEvent } from "../../Source/Cesium.js";
import { RequestScheduler } from "../../Source/Cesium.js";
import { Resource } from "../../Source/Cesium.js";
import { RuntimeError } from "../../Source/Cesium.js";
describe("Core/loadKTX", function () {
var validCompressed = new Uint8Array([
171,
75,
84,
88,
32,
49,
49,
187,
13,
10,
26,
10,
1,
2,
3,
4,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
241,
131,
0,
0,
8,
25,
0,
0,
4,
0,
0,
0,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
8,
0,
0,
0,
224,
7,
224,
7,
0,
0,
0,
0,
]);
var validCompressedMipmap = new Uint8Array([
171,
75,
84,
88,
32,
49,
49,
187,
13,
10,
26,
10,
1,
2,
3,
4,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
100,
141,
0,
0,
7,
25,
0,
0,
4,
0,
0,
0,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
3,
0,
0,
0,
52,
0,
0,
0,
19,
0,
0,
0,
67,
82,
78,
76,
73,
66,
95,
70,
79,
85,
82,
67,
67,
0,
69,
84,
67,
49,
0,
0,
23,
0,
0,
0,
75,
84,
88,
111,
114,
105,
101,
110,
116,
97,
116,
105,
111,
110,
0,
83,
61,
114,
44,
84,
61,
100,
0,
0,
8,
0,
0,
0,
255,
0,
0,
0,
255,
255,
0,
0,
8,
0,
0,
0,
255,
0,
0,
0,
255,
255,
0,
0,
8,
0,
0,
0,
255,
0,
0,
0,
255,
255,
0,
0,
]);
var validUncompressed = new Uint8Array([
171,
75,
84,
88,
32,
49,
49,
187,
13,
10,
26,
10,
1,
2,
3,
4,
1,
20,
0,
0,
1,
0,
0,
0,
8,
25,
0,
0,
88,
128,
0,
0,
8,
25,
0,
0,
4,
0,
0,
0,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
32,
0,
0,
0,
27,
0,
0,
0,
75,
84,
88,
79,
114,
105,
101,
110,
116,
97,
116,
105,
111,
110,
0,
83,
61,
114,
44,
84,
61,
100,
44,
82,
61,
105,
0,
0,
64,
0,
0,
0,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
0,
255,
]);
var validUncompressedMipmap = new Uint8Array([
171,
75,
84,
88,
32,
49,
49,
187,
13,
10,
26,
10,
1,
2,
3,
4,
1,
20,
0,
0,
1,
0,
0,
0,
7,
25,
0,
0,
81,
128,
0,
0,
7,
25,
0,
0,
4,
0,
0,
0,
4,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
3,
0,
0,
0,
52,
0,
0,
0,
19,
0,
0,
0,
67,
82,
78,
76,
73,
66,
95,
70,
79,
85,
82,
67,
67,
0,
82,
71,
66,
120,
0,
0,
23,
0,
0,
0,
75,
84,
88,
111,
114,
105,
101,
110,
116,
97,
116,
105,
111,
110,
0,
83,
61,
114,
44,
84,
61,
100,
0,
0,
48,
0,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
12,
0,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
255,
0,
0,
3,
0,
0,
0,
255,
0,
0,
0,
]);
var fakeXHR;
beforeEach(function () {
fakeXHR = jasmine.createSpyObj("XMLHttpRequest", [
"send",
"open",
"setRequestHeader",
"abort",
"getAllResponseHeaders",
]);
fakeXHR.simulateLoad = function (response) {
fakeXHR.simulateHttpResponse(200, response);
};
fakeXHR.simulateError = function () {
fakeXHR.response = "";
if (typeof fakeXHR.onerror === "function") {
fakeXHR.onerror();
}
};
fakeXHR.simulateHttpResponse = function (statusCode, response) {
fakeXHR.status = statusCode;
fakeXHR.response = response;
if (typeof fakeXHR.onload === "function") {
fakeXHR.onload();
}
};
spyOn(window, "XMLHttpRequest").and.returnValue(fakeXHR);
});
it("throws with no url", function () {
expect(function () {
loadKTX();
}).toThrowDeveloperError();
});
it("creates and sends request without any custom headers", function () {
var testUrl = "http://example.invalid/testuri";
loadKTX(testUrl);
expect(fakeXHR.open).toHaveBeenCalledWith("GET", testUrl, true);
expect(fakeXHR.setRequestHeader).not.toHaveBeenCalled();
expect(fakeXHR.send).toHaveBeenCalled();
});
it("returns a promise that rejects when the request errors", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateError();
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RequestErrorEvent);
expect(rejectedError.statusCode).toBeUndefined();
expect(rejectedError.response).toBeUndefined();
});
it("returns a promise that rejects when the request results in an HTTP error code", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var error = "some error";
fakeXHR.simulateHttpResponse(404, error);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RequestErrorEvent);
expect(rejectedError.statusCode).toEqual(404);
expect(rejectedError.response).toEqual(error);
});
it("returns a promise that resolves with undefined when the status code is 204", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolved = false;
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolved = true;
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateHttpResponse(204);
expect(resolved).toBe(true);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
});
it("returns a promise that resolves to an uncompressed texture when the request loads", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var response = validUncompressed.buffer;
fakeXHR.simulateLoad(response);
expect(resolvedValue).toBeDefined();
expect(resolvedValue.width).toEqual(4);
expect(resolvedValue.height).toEqual(4);
expect(
PixelFormat.isCompressedFormat(resolvedValue.internalFormat)
).toEqual(false);
expect(resolvedValue.bufferView).toBeDefined();
expect(rejectedError).toBeUndefined();
});
it("returns a promise that resolves to an uncompressed texture containing all mip levels of the original texture", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var response = validUncompressedMipmap.buffer;
fakeXHR.simulateLoad(response);
expect(resolvedValue).toBeDefined();
expect(resolvedValue.length).toEqual(3);
expect(resolvedValue[0].width).toEqual(4);
expect(resolvedValue[0].height).toEqual(4);
expect(
PixelFormat.isCompressedFormat(resolvedValue[0].internalFormat)
).toEqual(false);
expect(resolvedValue[0].bufferView).toBeDefined();
expect(rejectedError).toBeUndefined();
});
it("returns a promise that resolves to a compressed texture when the request loads", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var response = validCompressed.buffer;
fakeXHR.simulateLoad(response);
expect(resolvedValue).toBeDefined();
expect(resolvedValue.width).toEqual(4);
expect(resolvedValue.height).toEqual(4);
expect(
PixelFormat.isCompressedFormat(resolvedValue.internalFormat)
).toEqual(true);
expect(resolvedValue.bufferView).toBeDefined();
expect(rejectedError).toBeUndefined();
});
it("returns a promise that resolves to a compressed texture containing the all mip levels of the original texture", function () {
var testUrl = "http://example.invalid/testuri";
var promise = loadKTX(testUrl);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var response = validCompressedMipmap.buffer;
fakeXHR.simulateLoad(response);
expect(resolvedValue).toBeDefined();
expect(resolvedValue.length).toEqual(3);
expect(resolvedValue[0].width).toEqual(4);
expect(resolvedValue[0].height).toEqual(4);
expect(
PixelFormat.isCompressedFormat(resolvedValue[0].internalFormat)
).toEqual(true);
expect(resolvedValue[0].bufferView).toBeDefined();
expect(rejectedError).toBeUndefined();
});
it("cannot parse invalid KTX buffer", function () {
var invalidKTX = new Uint8Array(validCompressed);
invalidKTX[0] = 0;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual("Invalid KTX file.");
});
it("cannot parse KTX buffer with invalid endianness", function () {
var reinterprestBuffer = new Uint32Array(validCompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[3] = 0x01020304;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual("File is the wrong endianness.");
});
it("cannot parse KTX buffer with invalid internal format", function () {
var reinterprestBuffer = new Uint32Array(validCompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[7] = 0;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual(
"glInternalFormat is not a valid format."
);
});
it("cannot parse KTX buffer with compressed texture and invalid type", function () {
var reinterprestBuffer = new Uint32Array(validCompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[4] = 15;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual(
"glType must be zero when the texture is compressed."
);
});
it("cannot parse KTX buffer with compressed texture and invalid type size", function () {
var reinterprestBuffer = new Uint32Array(validCompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[5] = 15;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual(
"The type size for compressed textures must be 1."
);
});
it("cannot parse KTX buffer with uncompressed texture and base format is not the same as format", function () {
var reinterprestBuffer = new Uint32Array(validUncompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[8] = invalidKTX[6] + 1;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual(
"The base internal format must be the same as the format for uncompressed textures."
);
});
it("3D textures are unsupported", function () {
var reinterprestBuffer = new Uint32Array(validUncompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[11] = 15;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual("3D textures are unsupported.");
});
it("texture arrays are unsupported", function () {
var reinterprestBuffer = new Uint32Array(validUncompressed.buffer);
var invalidKTX = new Uint32Array(reinterprestBuffer);
invalidKTX[12] = 15;
var promise = loadKTX(invalidKTX.buffer);
var resolvedValue;
var rejectedError;
promise.then(
function (value) {
resolvedValue = value;
},
function (error) {
rejectedError = error;
}
);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeInstanceOf(RuntimeError);
expect(rejectedError.message).toEqual("Texture arrays are unsupported.");
});
it("cubemaps are supported", function () {
var reinterprestBuffer = new Uint32Array(validUncompressed.buffer);
var cubemapKTX = new Uint32Array(reinterprestBuffer);
cubemapKTX[13] = 6;
var promise = loadKTX(cubemapKTX.buffer);
promise.then(function (value) {
expect(value).toBeDefined();
});
});
it("returns undefined if the request is throttled", function () {
var oldMaximumRequests = RequestScheduler.maximumRequests;
RequestScheduler.maximumRequests = 0;
var promise = loadKTX(
new Resource({
url: "http://example.invalid/testuri",
request: new Request({
throttle: true,
}),
})
);
expect(promise).toBeUndefined();
RequestScheduler.maximumRequests = oldMaximumRequests;
});
});