Home | History | Annotate | Download | only in native
      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>
     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 
     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 
     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 
     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>
     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 
     98 TEST(libcore, Memory_peekShortNative_align_check) {
     99   memory_peek_test<jshort>(Memory_peekShortNative, 0x0102);
    100 }
    101 
    102 TEST(libcore, Memory_peekIntNative_align_check) {
    103   memory_peek_test<jint>(Memory_peekIntNative, 0x01020304);
    104 }
    105 
    106 TEST(libcore, Memory_peekLongNative_align_check) {
    107   memory_peek_test<jlong>(Memory_peekLongNative, 0x01020405060708ULL);
    108 }
    109 
    110 template<typename T>
    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 
    124 TEST(libcore, Memory_pokeShortNative_align_check) {
    125   memory_poke_test<jshort>(Memory_pokeShortNative, 0x0102);
    126 }
    127 
    128 TEST(libcore, Memory_pokeIntNative_align_check) {
    129   memory_poke_test<jint>(Memory_pokeIntNative, 0x01020304);
    130 }
    131 
    132 TEST(libcore, Memory_pokeLongNative_align_check) {
    133   memory_poke_test<jlong>(Memory_pokeLongNative, 0x0102030405060708ULL);
    134 }
    135