• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "v8.h"
2 #include "aliased_buffer.h"
3 #include "node_test_fixture.h"
4 
5 using node::AliasedBufferBase;
6 
7 class AliasBufferTest : public NodeTestFixture {};
8 
9 template <class NativeT>
CreateOracleValues(std::vector<NativeT> * buf)10 void CreateOracleValues(std::vector<NativeT>* buf) {
11   for (size_t i = 0, j = buf->size(); i < buf->size(); i++, j--) {
12     (*buf)[i] = static_cast<NativeT>(j);
13   }
14 }
15 
16 template <class NativeT, class V8T>
WriteViaOperator(AliasedBufferBase<NativeT,V8T> * aliasedBuffer,const std::vector<NativeT> & oracle)17 void WriteViaOperator(AliasedBufferBase<NativeT, V8T>* aliasedBuffer,
18                       const std::vector<NativeT>& oracle) {
19   // write through the API
20   for (size_t i = 0; i < oracle.size(); i++) {
21     (*aliasedBuffer)[i] = oracle[i];
22   }
23 }
24 
25 template <class NativeT, class V8T>
WriteViaSetValue(AliasedBufferBase<NativeT,V8T> * aliasedBuffer,const std::vector<NativeT> & oracle)26 void WriteViaSetValue(AliasedBufferBase<NativeT, V8T>* aliasedBuffer,
27                       const std::vector<NativeT>& oracle) {
28   // write through the API
29   for (size_t i = 0; i < oracle.size(); i++) {
30     aliasedBuffer->SetValue(i, oracle[i]);
31   }
32 }
33 
34 template <class NativeT, class V8T>
ReadAndValidate(v8::Isolate * isolate,v8::Local<v8::Context> context,AliasedBufferBase<NativeT,V8T> * aliasedBuffer,const std::vector<NativeT> & oracle)35 void ReadAndValidate(v8::Isolate* isolate,
36                      v8::Local<v8::Context> context,
37                      AliasedBufferBase<NativeT, V8T>* aliasedBuffer,
38                      const std::vector<NativeT>& oracle) {
39   // read through the API
40   for (size_t i = 0; i < oracle.size(); i++) {
41     NativeT v1 = (*aliasedBuffer)[i];
42     NativeT v2 = aliasedBuffer->GetValue(i);
43     EXPECT_TRUE(v1 == oracle[i]);
44     EXPECT_TRUE(v2 == oracle[i]);
45   }
46 
47   // validate size of JS Buffer
48   EXPECT_TRUE(aliasedBuffer->GetJSArray()->Length() == oracle.size());
49   EXPECT_TRUE(
50     aliasedBuffer->GetJSArray()->ByteLength() ==
51     (oracle.size() * sizeof(NativeT)));
52 
53   // validate operator * and GetBuffer are the same
54   EXPECT_TRUE(aliasedBuffer->GetNativeBuffer() == *(*aliasedBuffer));
55 
56   // read through the JS API
57   for (size_t i = 0; i < oracle.size(); i++) {
58     v8::Local<V8T> v8TypedArray = aliasedBuffer->GetJSArray();
59     v8::MaybeLocal<v8::Value> v = v8TypedArray->Get(context, i);
60     EXPECT_TRUE(v.IsEmpty() == false);
61     v8::Local<v8::Value> v2 = v.ToLocalChecked();
62     EXPECT_TRUE(v2->IsNumber());
63     v8::MaybeLocal<v8::Number> v3 = v2->ToNumber(context);
64     v8::Local<v8::Number> v4 = v3.ToLocalChecked();
65     NativeT actualValue = static_cast<NativeT>(v4->Value());
66     EXPECT_TRUE(actualValue == oracle[i]);
67   }
68 }
69 
70 template <class NativeT, class V8T>
ReadWriteTest(v8::Isolate * isolate)71 void ReadWriteTest(v8::Isolate* isolate) {
72   v8::Isolate::Scope isolate_scope(isolate);
73   v8::HandleScope handle_scope(isolate);
74   v8::Local<v8::Context> context = v8::Context::New(isolate);
75   v8::Context::Scope context_scope(context);
76 
77   const size_t size = 100;
78   AliasedBufferBase<NativeT, V8T> ab(isolate, size);
79   std::vector<NativeT> oracle(size);
80   CreateOracleValues(&oracle);
81   WriteViaOperator(&ab, oracle);
82   ReadAndValidate(isolate, context, &ab, oracle);
83 
84   WriteViaSetValue(&ab, oracle);
85 
86   // validate copy constructor
87   {
88     AliasedBufferBase<NativeT, V8T> ab2(ab);
89     ReadAndValidate(isolate, context, &ab2, oracle);
90   }
91   ReadAndValidate(isolate, context, &ab, oracle);
92 }
93 
94 template <
95     class NativeT_A, class V8T_A,
96     class NativeT_B, class V8T_B,
97     class NativeT_C, class V8T_C>
SharedBufferTest(v8::Isolate * isolate,size_t count_A,size_t count_B,size_t count_C)98 void SharedBufferTest(
99     v8::Isolate* isolate,
100     size_t count_A,
101     size_t count_B,
102     size_t count_C) {
103   v8::Isolate::Scope isolate_scope(isolate);
104   v8::HandleScope handle_scope(isolate);
105   v8::Local<v8::Context> context = v8::Context::New(isolate);
106   v8::Context::Scope context_scope(context);
107 
108   size_t sizeInBytes_A = count_A * sizeof(NativeT_A);
109   size_t sizeInBytes_B = count_B * sizeof(NativeT_B);
110   size_t sizeInBytes_C = count_C * sizeof(NativeT_C);
111 
112   AliasedBufferBase<uint8_t, v8::Uint8Array> rootBuffer(
113       isolate, sizeInBytes_A + sizeInBytes_B + sizeInBytes_C);
114   AliasedBufferBase<NativeT_A, V8T_A> ab_A(isolate, 0, count_A, rootBuffer);
115   AliasedBufferBase<NativeT_B, V8T_B> ab_B(
116       isolate, sizeInBytes_A, count_B, rootBuffer);
117   AliasedBufferBase<NativeT_C, V8T_C> ab_C(
118       isolate, sizeInBytes_A + sizeInBytes_B, count_C, rootBuffer);
119 
120   std::vector<NativeT_A> oracle_A(count_A);
121   std::vector<NativeT_B> oracle_B(count_B);
122   std::vector<NativeT_C> oracle_C(count_C);
123   CreateOracleValues(&oracle_A);
124   CreateOracleValues(&oracle_B);
125   CreateOracleValues(&oracle_C);
126 
127   WriteViaOperator(&ab_A, oracle_A);
128   WriteViaOperator(&ab_B, oracle_B);
129   WriteViaOperator(&ab_C, oracle_C);
130 
131   ReadAndValidate(isolate, context, &ab_A, oracle_A);
132   ReadAndValidate(isolate, context, &ab_B, oracle_B);
133   ReadAndValidate(isolate, context, &ab_C, oracle_C);
134 
135   WriteViaSetValue(&ab_A, oracle_A);
136   WriteViaSetValue(&ab_B, oracle_B);
137   WriteViaSetValue(&ab_C, oracle_C);
138 
139   ReadAndValidate(isolate, context, &ab_A, oracle_A);
140   ReadAndValidate(isolate, context, &ab_B, oracle_B);
141   ReadAndValidate(isolate, context, &ab_C, oracle_C);
142 }
143 
TEST_F(AliasBufferTest,Uint8Array)144 TEST_F(AliasBufferTest, Uint8Array) {
145   ReadWriteTest<uint8_t, v8::Uint8Array>(isolate_);
146 }
147 
TEST_F(AliasBufferTest,Int8Array)148 TEST_F(AliasBufferTest, Int8Array) {
149   ReadWriteTest<int8_t, v8::Int8Array>(isolate_);
150 }
151 
TEST_F(AliasBufferTest,Uint16Array)152 TEST_F(AliasBufferTest, Uint16Array) {
153   ReadWriteTest<uint16_t, v8::Uint16Array>(isolate_);
154 }
155 
TEST_F(AliasBufferTest,Int16Array)156 TEST_F(AliasBufferTest, Int16Array) {
157   ReadWriteTest<int16_t, v8::Int16Array>(isolate_);
158 }
159 
TEST_F(AliasBufferTest,Uint32Array)160 TEST_F(AliasBufferTest, Uint32Array) {
161   ReadWriteTest<uint32_t, v8::Uint32Array>(isolate_);
162 }
163 
TEST_F(AliasBufferTest,Int32Array)164 TEST_F(AliasBufferTest, Int32Array) {
165   ReadWriteTest<int32_t, v8::Int32Array>(isolate_);
166 }
167 
TEST_F(AliasBufferTest,Float32Array)168 TEST_F(AliasBufferTest, Float32Array) {
169   ReadWriteTest<float, v8::Float32Array>(isolate_);
170 }
171 
TEST_F(AliasBufferTest,Float64Array)172 TEST_F(AliasBufferTest, Float64Array) {
173   ReadWriteTest<double, v8::Float64Array>(isolate_);
174 }
175 
TEST_F(AliasBufferTest,SharedArrayBuffer1)176 TEST_F(AliasBufferTest, SharedArrayBuffer1) {
177   SharedBufferTest<
178       uint32_t, v8::Uint32Array,
179       double, v8::Float64Array,
180       int8_t, v8::Int8Array>(isolate_, 100, 80, 8);
181 }
182 
TEST_F(AliasBufferTest,SharedArrayBuffer2)183 TEST_F(AliasBufferTest, SharedArrayBuffer2) {
184   SharedBufferTest<
185       double, v8::Float64Array,
186       int8_t, v8::Int8Array,
187       double, v8::Float64Array>(isolate_, 100, 8, 8);
188 }
189 
TEST_F(AliasBufferTest,SharedArrayBuffer3)190 TEST_F(AliasBufferTest, SharedArrayBuffer3) {
191   SharedBufferTest<
192       int8_t, v8::Int8Array,
193       int8_t, v8::Int8Array,
194       double, v8::Float64Array>(isolate_, 1, 7, 8);
195 }
196 
TEST_F(AliasBufferTest,SharedArrayBuffer4)197 TEST_F(AliasBufferTest, SharedArrayBuffer4) {
198   SharedBufferTest<
199       int8_t, v8::Int8Array,
200       int8_t, v8::Int8Array,
201       int32_t, v8::Int32Array>(isolate_, 1, 3, 1);
202 }
203 
TEST_F(AliasBufferTest,OperatorOverloads)204 TEST_F(AliasBufferTest, OperatorOverloads) {
205   v8::Isolate::Scope isolate_scope(isolate_);
206   v8::HandleScope handle_scope(isolate_);
207   v8::Local<v8::Context> context = v8::Context::New(isolate_);
208   v8::Context::Scope context_scope(context);
209   const size_t size = 10;
210   AliasedBufferBase<uint32_t, v8::Uint32Array> ab{isolate_, size};
211 
212   EXPECT_EQ(static_cast<uint32_t>(1), ab[0] = 1);
213   EXPECT_EQ(static_cast<uint32_t>(4), ab[0] += 3);
214   EXPECT_EQ(static_cast<uint32_t>(2), ab[0] -= 2);
215   EXPECT_EQ(static_cast<uint32_t>(-2), -ab[0]);
216 }
217 
TEST_F(AliasBufferTest,OperatorOverloadsRefs)218 TEST_F(AliasBufferTest, OperatorOverloadsRefs) {
219   v8::Isolate::Scope isolate_scope(isolate_);
220   v8::HandleScope handle_scope(isolate_);
221   v8::Local<v8::Context> context = v8::Context::New(isolate_);
222   v8::Context::Scope context_scope(context);
223   AliasedBufferBase<uint32_t, v8::Uint32Array> ab{isolate_, 2};
224   using Reference = AliasedBufferBase<uint32_t, v8::Uint32Array>::Reference;
225   Reference ref = ab[0];
226   Reference ref_value = ab[1] = 2;
227 
228   EXPECT_EQ(static_cast<uint32_t>(2), ref = ref_value);
229   EXPECT_EQ(static_cast<uint32_t>(4), ref += ref_value);
230   EXPECT_EQ(static_cast<uint32_t>(2), ref -= ref_value);
231   EXPECT_EQ(static_cast<uint32_t>(-2), -ref);
232 }
233