1 /*
2  * Copyright (C) 2015 The Android Open Source Project
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 
17 #include "luni/src/main/native/libcore_io_Memory.cpp"
18 
19 #include <stdlib.h>
20 
21 #include <functional>
22 
23 #include <gtest/gtest.h>
24 
25 #define ALIGNMENT 8
26 
27 template<typename T, size_t NUM_ELEMENTS>
swap_align_test(void (* swap_func)(T *,const T *,size_t),std::function<void (T *,T *,uint64_t)> init_func)28 void swap_align_test(void (*swap_func)(T*, const T*, size_t),
29                      std::function<void (T*, T*, uint64_t)> init_func) {
30   uint8_t* dst = nullptr;
31   uint8_t* src = nullptr;
32   ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&dst), ALIGNMENT,
33                               sizeof(T) * NUM_ELEMENTS + ALIGNMENT));
34   ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&src), ALIGNMENT,
35                               sizeof(T) * NUM_ELEMENTS + ALIGNMENT));
36 
37   T src_buf[NUM_ELEMENTS];
38   T dst_buf[NUM_ELEMENTS];
39   for (uint64_t i = 0; i < NUM_ELEMENTS; i++) {
40     init_func(&src_buf[i], &dst_buf[i], i);
41   }
42 
43   // Vary a few alignments.
44   for (size_t dst_align = 0; dst_align < ALIGNMENT; dst_align++) {
45     T* dst_aligned = reinterpret_cast<T*>(&dst[dst_align]);
46     for (size_t src_align = 0; src_align < ALIGNMENT; src_align++) {
47       T* src_aligned = reinterpret_cast<T*>(&src[src_align]);
48       memset(dst_aligned, 0, sizeof(T) * NUM_ELEMENTS);
49       memcpy(src_aligned, src_buf, sizeof(T) * NUM_ELEMENTS);
50       swap_func(dst_aligned, src_aligned, NUM_ELEMENTS);
51       ASSERT_EQ(0, memcmp(dst_buf, dst_aligned, sizeof(T) * NUM_ELEMENTS))
52           << "Failed at dst align " << dst_align << " src align " << src_align;
53     }
54   }
55   free(dst);
56   free(src);
57 }
58 
TEST(libcore,swapShorts_align_test)59 TEST(libcore, swapShorts_align_test) {
60   // Use an odd number to guarantee that the last 16-bit swap code
61   // is executed.
62   swap_align_test<jshort, 9> (swapShorts, [] (jshort* src, jshort* dst, uint64_t i) {
63     *src = ((2*i) << 8) | (2*(i+1));
64     *dst = (2*i) | ((2*(i+1)) << 8);
65   });
66 }
67 
TEST(libcore,swapInts_align_test)68 TEST(libcore, swapInts_align_test) {
69   swap_align_test<jint, 10> (swapInts, [] (jint* src, jint* dst, uint64_t i) {
70     *src = ((4*i) << 24) | ((4*(i+1)) << 16) | ((4*(i+2)) << 8) | (4*(i+3));
71     *dst = (4*i) | ((4*(i+1)) << 8) | ((4*(i+2)) << 16) | ((4*(i+3)) << 24);
72   });
73 }
74 
TEST(libcore,swapLongs_align_test)75 TEST(libcore, swapLongs_align_test) {
76   swap_align_test<jlong, 10> (swapLongs, [] (jlong* src, jlong* dst, uint64_t i) {
77     *src = ((8*i) << 56) | ((8*(i+1)) << 48) | ((8*(i+2)) << 40) | ((8*(i+3)) << 32) |
78         ((8*(i+4)) << 24) | ((8*(i+5)) << 16) | ((8*(i+6)) << 8) | (8*(i+7));
79     *dst = (8*i) | ((8*(i+1)) << 8) | ((8*(i+2)) << 16) | ((8*(i+3)) << 24) |
80         ((8*(i+4)) << 32) | ((8*(i+5)) << 40) | ((8*(i+6)) << 48) | ((8*(i+7)) << 56);
81   });
82 }
83 
84 template<typename T>
memory_peek_test(T (* peek_func)(JNIEnv *,jclass,jlong),T value)85 void memory_peek_test(T (*peek_func)(JNIEnv*, jclass, jlong), T value) {
86   T* src = nullptr;
87   ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&src), ALIGNMENT,
88                               sizeof(T) + ALIGNMENT));
89   for (size_t i = 0; i < ALIGNMENT; i++) {
90     jlong src_aligned = reinterpret_cast<jlong>(src) + i;
91     memcpy(reinterpret_cast<void*>(src_aligned), &value, sizeof(T));
92     T result = peek_func(nullptr, nullptr, src_aligned);
93     ASSERT_EQ(value, result);
94   }
95   free(src);
96 }
97 
TEST(libcore,Memory_peekShortNative_align_check)98 TEST(libcore, Memory_peekShortNative_align_check) {
99   memory_peek_test<jshort>(Memory_peekShortNative, 0x0102);
100 }
101 
TEST(libcore,Memory_peekIntNative_align_check)102 TEST(libcore, Memory_peekIntNative_align_check) {
103   memory_peek_test<jint>(Memory_peekIntNative, 0x01020304);
104 }
105 
TEST(libcore,Memory_peekLongNative_align_check)106 TEST(libcore, Memory_peekLongNative_align_check) {
107   memory_peek_test<jlong>(Memory_peekLongNative, 0x01020405060708ULL);
108 }
109 
110 template<typename T>
memory_poke_test(void (* poke_func)(JNIEnv *,jclass,jlong,T),T value)111 void memory_poke_test(void (*poke_func)(JNIEnv*, jclass, jlong, T), T value) {
112   T* dst = nullptr;
113   ASSERT_EQ(0, posix_memalign(reinterpret_cast<void**>(&dst), ALIGNMENT,
114                               sizeof(T) + ALIGNMENT));
115   for(size_t i = 0; i < ALIGNMENT; i++) {
116     memset(dst, 0, sizeof(T) + ALIGNMENT);
117     jlong dst_aligned = reinterpret_cast<jlong>(dst) + i;
118     poke_func(nullptr, nullptr, dst_aligned, value);
119     ASSERT_EQ(0, memcmp(reinterpret_cast<void*>(dst_aligned), &value, sizeof(T)));
120   }
121   free(dst);
122 }
123 
TEST(libcore,Memory_pokeShortNative_align_check)124 TEST(libcore, Memory_pokeShortNative_align_check) {
125   memory_poke_test<jshort>(Memory_pokeShortNative, 0x0102);
126 }
127 
TEST(libcore,Memory_pokeIntNative_align_check)128 TEST(libcore, Memory_pokeIntNative_align_check) {
129   memory_poke_test<jint>(Memory_pokeIntNative, 0x01020304);
130 }
131 
TEST(libcore,Memory_pokeLongNative_align_check)132 TEST(libcore, Memory_pokeLongNative_align_check) {
133   memory_poke_test<jlong>(Memory_pokeLongNative, 0x0102030405060708ULL);
134 }
135