1 /*
   2  * Copyright (c) 2018, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 import org.testng.annotations.*;
  27 
  28 import java.lang.invoke.MethodHandles;
  29 import java.lang.reflect.Proxy;
  30 import java.nio.file.Path;
  31 import java.util.stream.Stream;
  32 
  33 import static org.testng.Assert.assertEquals;
  34 import static org.testng.Assert.assertNotNull;
  35 import static org.testng.Assert.assertTrue;
  36 
  37 
  38 /*
  39  * @test
  40  * @modules jdk.jextract
  41  * @build ConstantsTest
  42  * @run testng ConstantsTest
  43  */
  44 public class ConstantsTest extends JextractToolRunner {
  45 
  46     Object[] constants;
  47     Path clzPath;
  48     Path dirPath;
  49 
  50     @BeforeTest
  51     public void setup() {
  52         clzPath = getOutputFilePath("ConstantsTest.c.jar");
  53         dirPath = getOutputFilePath("ConstantsTest.c.dir");
  54         checkSuccess(null,"-o", clzPath.toString(), "-d", dirPath.toString(),
  55                 getInputFilePath("constants.h").toString());
  56         Class<?>[] cls = {
  57                 loadClass("constants", clzPath),
  58                 loadClass("constants", dirPath)
  59         };
  60         constants = new Object[cls.length];
  61         for (int i = 0 ; i < cls.length ; i++) {
  62             Class<?> cl = cls[i];
  63             constants[i] = Proxy.newProxyInstance(cl.getClassLoader(),
  64                     new Class<?>[]{ cl },
  65                     (proxy, method, args) -> MethodHandles.privateLookupIn(cl, MethodHandles.lookup())
  66                                 .unreflectSpecial(method, cl)
  67                                 .bindTo(proxy)
  68                                 .invokeWithArguments(args));
  69         }
  70     }
  71 
  72     @AfterTest
  73     public void cleanup() {
  74         deleteFile(clzPath);
  75         deleteDir(dirPath);
  76     }
  77 
  78 
  79     @Test(dataProvider = "definedConstants")
  80     public void checkConstantsSignatures(String name, Class<?> type, Object value) {
  81         for (Object c : constants) {
  82             checkMethod(c.getClass(), name, type);
  83         }
  84     }
  85 
  86     @Test(dataProvider = "definedConstants")
  87     public void checkConstantsValues(String name, Class<?> type, Object value) throws ReflectiveOperationException {
  88         for (Object c : constants) {
  89             Object actual = c.getClass().getDeclaredMethod(name).invoke(c);
  90             assertEquals(actual, value);
  91         }
  92     }
  93 
  94     @Test(dataProvider = "missingConstants")
  95     public void checkMissingConstants(String name) {
  96         for (Object c : constants) {
  97             assertTrue(Stream.of(c.getClass().getDeclaredMethods())
  98                     .noneMatch(m -> m.getName().equals(name)));
  99         }
 100     }
 101 
 102     @DataProvider
 103     public static Object[][] definedConstants() {
 104         return new Object[][] {
 105                 { "ZERO", int.class, 0 },
 106                 { "ONE", int.class, 1 },
 107                 { "TWO", int.class, 2 },
 108                 { "THREE", int.class, 3 },
 109                 { "FOUR", long.class, 4L },
 110                 { "FIVE", long.class, 5L },
 111                 { "SIX", int.class, 6 },
 112                 { "STR", String.class, "Hello" },
 113                 { "FLOAT_VALUE", float.class, 1.32f },
 114                 { "DOUBLE_VALUE", double.class, 1.32 },
 115                 { "QUOTE", String.class, "QUOTE" },
 116                 { "CHAR_VALUE", char.class, 'h'},
 117                 { "SUB", int.class, 7 }
 118         };
 119     }
 120 
 121     @DataProvider
 122     public static Object[][] missingConstants() {
 123         return new Object[][] {
 124                 { "ID" },
 125                 { "SUM" },
 126                 { "BLOCK_BEGIN" },
 127                 { "BLOCK_END" },
 128                 { "INTEGER_MAX_VALUE" },
 129                 { "CYCLIC_1" },
 130                 { "CYCLIC_2" }
 131         };
 132     }
 133 }