js/src/jsapi-tests/testMappedArrayBuffer.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jsapi-tests/testMappedArrayBuffer.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,188 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + */
     1.7 +
     1.8 +#ifdef XP_UNIX
     1.9 +#include <fcntl.h>
    1.10 +#include <stdio.h>
    1.11 +#include <string.h>
    1.12 +#include <sys/stat.h>
    1.13 +#include <sys/types.h>
    1.14 +#include <unistd.h>
    1.15 +
    1.16 +#include "jsfriendapi.h"
    1.17 +#include "js/StructuredClone.h"
    1.18 +#include "jsapi-tests/tests.h"
    1.19 +#include "vm/ArrayBufferObject.h"
    1.20 +
    1.21 +const char test_data[] = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    1.22 +const char test_filename[] = "temp-bug945152_MappedArrayBuffer";
    1.23 +
    1.24 +BEGIN_TEST(testMappedArrayBuffer_bug945152)
    1.25 +{
    1.26 +    TempFile test_file;
    1.27 +    FILE *test_stream = test_file.open(test_filename);
    1.28 +    CHECK(fputs(test_data, test_stream) != EOF);
    1.29 +    test_file.close();
    1.30 +
    1.31 +    // Offset 0.
    1.32 +    CHECK(TestCreateObject(0, 12));
    1.33 +
    1.34 +    // Aligned offset.
    1.35 +    CHECK(TestCreateObject(8, 12));
    1.36 +
    1.37 +    // Unaligned offset.
    1.38 +    CHECK(CreateNewObject(11, 12) == nullptr);
    1.39 +
    1.40 +    // Offset + length greater than file size.
    1.41 +    CHECK(CreateNewObject(8, sizeof(test_data) - 7) == nullptr);
    1.42 +
    1.43 +    // Release the mapped content.
    1.44 +    CHECK(TestReleaseContents());
    1.45 +
    1.46 +    // Neuter mapped array buffer.
    1.47 +    CHECK(TestNeuterObject());
    1.48 +
    1.49 +    // Clone mapped array buffer.
    1.50 +    CHECK(TestCloneObject());
    1.51 +
    1.52 +    // Steal mapped array buffer contents.
    1.53 +    CHECK(TestStealContents());
    1.54 +
    1.55 +    // Transfer mapped array buffer contents.
    1.56 +    CHECK(TestTransferObject());
    1.57 +
    1.58 +    test_file.remove();
    1.59 +
    1.60 +    return true;
    1.61 +}
    1.62 +
    1.63 +JSObject *CreateNewObject(const int offset, const int length)
    1.64 +{
    1.65 +    int fd = open(test_filename, O_RDONLY);
    1.66 +    void *ptr = JS_CreateMappedArrayBufferContents(fd, offset, length);
    1.67 +    close(fd);
    1.68 +    if (!ptr)
    1.69 +        return nullptr;
    1.70 +    JSObject *obj = JS_NewMappedArrayBufferWithContents(cx, length, ptr);
    1.71 +    if (!obj) {
    1.72 +        JS_ReleaseMappedArrayBufferContents(ptr, length);
    1.73 +        return nullptr;
    1.74 +    }
    1.75 +    return obj;
    1.76 +}
    1.77 +
    1.78 +bool VerifyObject(JS::HandleObject obj, const int offset, const int length, const bool mapped)
    1.79 +{
    1.80 +    CHECK(obj);
    1.81 +    CHECK(JS_IsArrayBufferObject(obj));
    1.82 +    CHECK_EQUAL(JS_GetArrayBufferByteLength(obj), length);
    1.83 +    if (mapped)
    1.84 +        CHECK(JS_IsMappedArrayBufferObject(obj));
    1.85 +    else
    1.86 +        CHECK(!JS_IsMappedArrayBufferObject(obj));
    1.87 +    const char *data = reinterpret_cast<const char *>(JS_GetArrayBufferData(obj));
    1.88 +    CHECK(data);
    1.89 +    CHECK(memcmp(data, test_data + offset, length) == 0);
    1.90 +
    1.91 +    return true;
    1.92 +}
    1.93 +
    1.94 +bool TestCreateObject(const int offset, const int length)
    1.95 +{
    1.96 +    JS::RootedObject obj(cx, CreateNewObject(offset, length));
    1.97 +    CHECK(VerifyObject(obj, offset, length, true));
    1.98 +
    1.99 +    return true;
   1.100 +}
   1.101 +
   1.102 +bool TestReleaseContents()
   1.103 +{
   1.104 +    int fd = open(test_filename, O_RDONLY);
   1.105 +    void *ptr = JS_CreateMappedArrayBufferContents(fd, 0, 12);
   1.106 +    close(fd);
   1.107 +    if (!ptr)
   1.108 +        return false;
   1.109 +    JS_ReleaseMappedArrayBufferContents(ptr, 12);
   1.110 +
   1.111 +    return true;
   1.112 +}
   1.113 +
   1.114 +bool TestNeuterObject()
   1.115 +{
   1.116 +    JS::RootedObject obj(cx, CreateNewObject(8, 12));
   1.117 +    CHECK(obj);
   1.118 +    JS_NeuterArrayBuffer(cx, obj, ChangeData);
   1.119 +    CHECK(isNeutered(obj));
   1.120 +
   1.121 +    return true;
   1.122 +}
   1.123 +
   1.124 +bool TestCloneObject()
   1.125 +{
   1.126 +    JS::RootedObject obj1(cx, CreateNewObject(8, 12));
   1.127 +    CHECK(obj1);
   1.128 +    JSAutoStructuredCloneBuffer cloned_buffer;
   1.129 +    JS::RootedValue v1(cx, OBJECT_TO_JSVAL(obj1));
   1.130 +    const JSStructuredCloneCallbacks *callbacks = js::GetContextStructuredCloneCallbacks(cx);
   1.131 +    CHECK(cloned_buffer.write(cx, v1, callbacks, nullptr));
   1.132 +    JS::RootedValue v2(cx);
   1.133 +    CHECK(cloned_buffer.read(cx, &v2, callbacks, nullptr));
   1.134 +    JS::RootedObject obj2(cx, JSVAL_TO_OBJECT(v2));
   1.135 +    CHECK(VerifyObject(obj2, 8, 12, false));
   1.136 +
   1.137 +    return true;
   1.138 +}
   1.139 +
   1.140 +bool TestStealContents()
   1.141 +{
   1.142 +    JS::RootedObject obj(cx, CreateNewObject(8, 12));
   1.143 +    CHECK(obj);
   1.144 +    void *contents = JS_StealArrayBufferContents(cx, obj);
   1.145 +    CHECK(contents);
   1.146 +    CHECK(memcmp(contents, test_data + 8, 12) == 0);
   1.147 +    CHECK(isNeutered(obj));
   1.148 +
   1.149 +    return true;
   1.150 +}
   1.151 +
   1.152 +bool TestTransferObject()
   1.153 +{
   1.154 +    JS::RootedObject obj1(cx, CreateNewObject(8, 12));
   1.155 +    CHECK(obj1);
   1.156 +    JS::RootedValue v1(cx, OBJECT_TO_JSVAL(obj1));
   1.157 +
   1.158 +    // Create an Array of transferable values.
   1.159 +    JS::AutoValueVector argv(cx);
   1.160 +    argv.append(v1);
   1.161 +    JS::RootedObject obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::subarray(argv, 0, 1)));
   1.162 +    CHECK(obj);
   1.163 +    JS::RootedValue transferable(cx, OBJECT_TO_JSVAL(obj));
   1.164 +
   1.165 +    JSAutoStructuredCloneBuffer cloned_buffer;
   1.166 +    const JSStructuredCloneCallbacks *callbacks = js::GetContextStructuredCloneCallbacks(cx);
   1.167 +    CHECK(cloned_buffer.write(cx, v1, transferable, callbacks, nullptr));
   1.168 +    JS::RootedValue v2(cx);
   1.169 +    CHECK(cloned_buffer.read(cx, &v2, callbacks, nullptr));
   1.170 +    JS::RootedObject obj2(cx, JSVAL_TO_OBJECT(v2));
   1.171 +    CHECK(VerifyObject(obj2, 8, 12, true));
   1.172 +    CHECK(isNeutered(obj1));
   1.173 +
   1.174 +    return true;
   1.175 +}
   1.176 +
   1.177 +bool isNeutered(JS::HandleObject obj)
   1.178 +{
   1.179 +    JS::RootedValue v(cx);
   1.180 +    return JS_GetProperty(cx, obj, "byteLength", &v) && v.toInt32() == 0;
   1.181 +}
   1.182 +
   1.183 +static void GC(JSContext *cx)
   1.184 +{
   1.185 +    JS_GC(JS_GetRuntime(cx));
   1.186 +    // Trigger another to wait for background finalization to end.
   1.187 +    JS_GC(JS_GetRuntime(cx));
   1.188 +}
   1.189 +
   1.190 +END_TEST(testMappedArrayBuffer_bug945152)
   1.191 +#endif

mercurial