1 /*
   2  *  Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  *  This code is free software; you can redistribute it and/or modify it
   6  *  under the terms of the GNU General Public License version 2 only, as
   7  *  published by the Free Software Foundation.
   8  *
   9  *  This code is distributed in the hope that it will be useful, but WITHOUT
  10  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  *  version 2 for more details (a copy is included in the LICENSE file that
  13  *  accompanied this code).
  14  *
  15  *  You should have received a copy of the GNU General Public License version
  16  *  2 along with this work; if not, write to the Free Software Foundation,
  17  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  *  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  *  or visit www.oracle.com if you need additional information or have any
  21  *  questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @requires os.family != "windows"
  27  * @run testng UnalignedStructTest
  28  */
  29 
  30 import org.testng.annotations.*;
  31 
  32 import java.foreign.Libraries;
  33 import java.foreign.Scope;
  34 import java.foreign.annotations.NativeFunction;
  35 import java.foreign.annotations.NativeGetter;
  36 import java.foreign.annotations.NativeHeader;
  37 import java.foreign.annotations.NativeSetter;
  38 import java.foreign.annotations.NativeStruct;
  39 import java.foreign.memory.Struct;
  40 import java.lang.invoke.MethodHandles;
  41 import java.util.Random;
  42 import java.util.stream.IntStream;
  43 
  44 import static org.testng.Assert.*;
  45 
  46 @Test
  47 public class UnalignedStructTest {
  48 
  49     @NativeHeader
  50     interface unaligned {
  51         @NativeFunction("(${str} ${str})i16")
  52         short unaligned_sum_i1(Str str, Str str2);
  53         @NativeFunction("(${str} ${str})i16")
  54         short unaligned_sum_i2(Str str1, Str str2);
  55 
  56         @NativeStruct("[ f128 i16(i1) i16(i2) ](str)")
  57         interface Str extends Struct<Str> {
  58             @NativeGetter("i1")
  59             short i1$get();
  60             @NativeGetter("i2")
  61             short i2$get();
  62             @NativeSetter("i1")
  63             void i1$set(short i1);
  64             @NativeSetter("i2")
  65             void i2$set(short i2);
  66         }
  67     }
  68 
  69     static unaligned lib =
  70             Libraries.bind(unaligned.class,
  71                     Libraries.loadLibrary(MethodHandles.lookup(), "UnalignedStruct"));
  72 
  73 
  74     @Test(dataProvider = "pairs")
  75     public void testUnalignedCalls(short i1, short i2) {
  76         try (Scope sc = Scope.globalScope().fork()) {
  77             unaligned.Str str = sc.allocateStruct(unaligned.Str.class);
  78             str.i1$set(i1);
  79             str.i2$set(i2);
  80             //sanity check
  81             assertEquals(str.i1$get(), i1);
  82             assertEquals(str.i2$get(), i2);
  83             //real check
  84             assertEquals(lib.unaligned_sum_i1(str, str), i1 + i1);
  85             assertEquals(lib.unaligned_sum_i2(str, str), i2 + i2);
  86         }
  87     }
  88 
  89     static IntStream intStream() {
  90         //avoid overflow
  91         return new Random().ints(Byte.MIN_VALUE, Byte.MAX_VALUE)
  92                 .limit(100);
  93     }
  94 
  95     @DataProvider
  96     public static Object[][] pairs() {
  97         int[] i1Arr = intStream().toArray();
  98         int[] i2Arr = intStream().toArray();
  99         Object[][] res = new Object[i1Arr.length][];
 100         for (int i = 0 ; i < i1Arr.length ; i++) {
 101             res[i] = new Object[] { (short)i1Arr[i], (short)i2Arr[i]};
 102         }
 103         return res;
 104     }
 105 }