diff options
Diffstat (limited to 'z3/subprojects')
12 files changed, 463 insertions, 0 deletions
diff --git a/z3/subprojects/solver-darwin-aarch64/build.gradle.kts b/z3/subprojects/solver-darwin-aarch64/build.gradle.kts new file mode 100644 index 00000000..21c9739c --- /dev/null +++ b/z3/subprojects/solver-darwin-aarch64/build.gradle.kts | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.z3.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | val classifier = "z3-${version}-arm64-osx-11.0" | ||
12 | val library = "z3java-darwin-aarch64" | ||
13 | |||
14 | dependencies { | ||
15 | z3("Z3Prover:z3:${version}:${classifier}@zip") | ||
16 | } | ||
17 | |||
18 | val extractZ3Libs by tasks.registering(Sync::class) { | ||
19 | dependsOn(configurations.z3) | ||
20 | from({ | ||
21 | val zipFile = configurations.z3.map { it.singleFile } | ||
22 | zipTree(zipFile).matching { | ||
23 | include("${classifier}/bin/*.so") | ||
24 | includeEmptyDirs = false | ||
25 | } | ||
26 | }) | ||
27 | eachFile { | ||
28 | val pathInBin = relativePath.segments.drop(2).toTypedArray() | ||
29 | relativePath = RelativePath(true, library, *pathInBin) | ||
30 | } | ||
31 | into(layout.buildDirectory.dir("z3-extracted")) | ||
32 | } | ||
33 | |||
34 | sourceSets.main { | ||
35 | resources.srcDir(extractZ3Libs) | ||
36 | } | ||
diff --git a/z3/subprojects/solver-darwin-x86-64/build.gradle.kts b/z3/subprojects/solver-darwin-x86-64/build.gradle.kts new file mode 100644 index 00000000..75e59267 --- /dev/null +++ b/z3/subprojects/solver-darwin-x86-64/build.gradle.kts | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.z3.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | val classifier = "z3-${version}-x64-osx-10.16" | ||
12 | val library = "z3java-darwin-x86-64" | ||
13 | |||
14 | dependencies { | ||
15 | z3("Z3Prover:z3:${version}:${classifier}@zip") | ||
16 | } | ||
17 | |||
18 | val extractZ3Libs by tasks.registering(Sync::class) { | ||
19 | dependsOn(configurations.z3) | ||
20 | from({ | ||
21 | val zipFile = configurations.z3.map { it.singleFile } | ||
22 | zipTree(zipFile).matching { | ||
23 | include("${classifier}/bin/*.so") | ||
24 | includeEmptyDirs = false | ||
25 | } | ||
26 | }) | ||
27 | eachFile { | ||
28 | val pathInBin = relativePath.segments.drop(2).toTypedArray() | ||
29 | relativePath = RelativePath(true, library, *pathInBin) | ||
30 | } | ||
31 | into(layout.buildDirectory.dir("z3-extracted")) | ||
32 | } | ||
33 | |||
34 | sourceSets.main { | ||
35 | resources.srcDir(extractZ3Libs) | ||
36 | } | ||
diff --git a/z3/subprojects/solver-linux-aarch64/build.gradle.kts b/z3/subprojects/solver-linux-aarch64/build.gradle.kts new file mode 100644 index 00000000..a8e7e259 --- /dev/null +++ b/z3/subprojects/solver-linux-aarch64/build.gradle.kts | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.z3.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | tasks.jar { | ||
12 | // License information is redundant here, since it already gets added to the POM. | ||
13 | exclude("**/*.license") | ||
14 | } | ||
diff --git a/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3.so b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3.so new file mode 100755 index 00000000..574ee3ab --- /dev/null +++ b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3.so | |||
Binary files differ | |||
diff --git a/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3.so.license b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3.so.license new file mode 100644 index 00000000..0993dbf7 --- /dev/null +++ b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3.so.license | |||
@@ -0,0 +1,6 @@ | |||
1 | Copyright (c) Microsoft Corporations | ||
2 | |||
3 | SPDX-License-Identifier: MIT | ||
4 | |||
5 | This file was created from the Z3 4.12.6 release sources using the | ||
6 | z3/docker/cross_build.sh script in this repository. | ||
diff --git a/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3java.so b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3java.so new file mode 100755 index 00000000..aace2c30 --- /dev/null +++ b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3java.so | |||
Binary files differ | |||
diff --git a/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3java.so.license b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3java.so.license new file mode 100644 index 00000000..0993dbf7 --- /dev/null +++ b/z3/subprojects/solver-linux-aarch64/src/main/resources/z3java-linux-aarch64/libz3java.so.license | |||
@@ -0,0 +1,6 @@ | |||
1 | Copyright (c) Microsoft Corporations | ||
2 | |||
3 | SPDX-License-Identifier: MIT | ||
4 | |||
5 | This file was created from the Z3 4.12.6 release sources using the | ||
6 | z3/docker/cross_build.sh script in this repository. | ||
diff --git a/z3/subprojects/solver-linux-x86-64/build.gradle.kts b/z3/subprojects/solver-linux-x86-64/build.gradle.kts new file mode 100644 index 00000000..89c737b6 --- /dev/null +++ b/z3/subprojects/solver-linux-x86-64/build.gradle.kts | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.z3.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | val classifier = "z3-${version}-x64-glibc-2.31" | ||
12 | val library = "z3java-linux-x86-64" | ||
13 | |||
14 | dependencies { | ||
15 | z3("Z3Prover:z3:${version}:${classifier}@zip") | ||
16 | } | ||
17 | |||
18 | val extractZ3Libs by tasks.registering(Sync::class) { | ||
19 | dependsOn(configurations.z3) | ||
20 | from({ | ||
21 | val zipFile = configurations.z3.map { it.singleFile } | ||
22 | zipTree(zipFile).matching { | ||
23 | include("${classifier}/bin/*.so") | ||
24 | includeEmptyDirs = false | ||
25 | } | ||
26 | }) | ||
27 | eachFile { | ||
28 | val pathInBin = relativePath.segments.drop(2).toTypedArray() | ||
29 | relativePath = RelativePath(true, library, *pathInBin) | ||
30 | } | ||
31 | into(layout.buildDirectory.dir("z3-extracted")) | ||
32 | } | ||
33 | |||
34 | sourceSets.main { | ||
35 | resources.srcDir(extractZ3Libs) | ||
36 | } | ||
diff --git a/z3/subprojects/solver-win32-x86-64/build.gradle.kts b/z3/subprojects/solver-win32-x86-64/build.gradle.kts new file mode 100644 index 00000000..c5fa0421 --- /dev/null +++ b/z3/subprojects/solver-win32-x86-64/build.gradle.kts | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.z3.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | val classifier = "z3-${version}-x64-win" | ||
12 | val library = "z3java-win32-x86-64" | ||
13 | |||
14 | dependencies { | ||
15 | z3("Z3Prover:z3:${version}:${classifier}@zip") | ||
16 | } | ||
17 | |||
18 | val extractZ3Libs by tasks.registering(Sync::class) { | ||
19 | dependsOn(configurations.z3) | ||
20 | from({ | ||
21 | val zipFile = configurations.z3.map { it.singleFile } | ||
22 | zipTree(zipFile).matching { | ||
23 | include("${classifier}/bin/*.dll") | ||
24 | // Do not include .NET assembly. | ||
25 | exclude("${classifier}/bin/Microsoft.Z3.dll") | ||
26 | includeEmptyDirs = false | ||
27 | } | ||
28 | }) | ||
29 | eachFile { | ||
30 | val pathInBin = relativePath.segments.drop(2).toTypedArray() | ||
31 | relativePath = RelativePath(true, library, *pathInBin) | ||
32 | } | ||
33 | into(layout.buildDirectory.dir("z3-extracted")) | ||
34 | } | ||
35 | |||
36 | sourceSets.main { | ||
37 | resources.srcDir(extractZ3Libs) | ||
38 | } | ||
diff --git a/z3/subprojects/solver/build.gradle.kts b/z3/subprojects/solver/build.gradle.kts new file mode 100644 index 00000000..7e898b3e --- /dev/null +++ b/z3/subprojects/solver/build.gradle.kts | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | |||
7 | import tools.refinery.z3.gradle.ClassFilePatcher | ||
8 | |||
9 | plugins { | ||
10 | id("tools.refinery.z3.gradle.java-library") | ||
11 | } | ||
12 | |||
13 | val classifier = "z3-${version}-x64-glibc-2.31" | ||
14 | val extractedClassesDir = layout.buildDirectory.dir("z3-extracted") | ||
15 | val extractedSourcesDir = layout.buildDirectory.dir("z3-sources") | ||
16 | |||
17 | java { | ||
18 | withJavadocJar() | ||
19 | withSourcesJar() | ||
20 | } | ||
21 | |||
22 | val z3Source: Configuration by configurations.creating { | ||
23 | isCanBeConsumed = false | ||
24 | isCanBeResolved = true | ||
25 | } | ||
26 | |||
27 | val extractZ3Jar by tasks.registering(Sync::class) { | ||
28 | dependsOn(configurations.z3) | ||
29 | from({ | ||
30 | val zipFile = configurations.z3.map { it.singleFile } | ||
31 | val jarFile = zipTree(zipFile).matching { | ||
32 | include("${classifier}/bin/com.microsoft.z3.jar") | ||
33 | }.singleFile | ||
34 | zipTree(jarFile).matching { | ||
35 | exclude("META-INF/MANIFEST.MF") | ||
36 | includeEmptyDirs = false | ||
37 | } | ||
38 | }) | ||
39 | into(extractedClassesDir) | ||
40 | doLast { | ||
41 | // The class initializer off {@see com.microsoft.z3.Native} will try to load the Z3 native libraries | ||
42 | // from the system default library path unless the {@code z3.skipLibraryLoad} system property is set. | ||
43 | // Since we don't control the library path or system properties, we remove the class initializer entirely. | ||
44 | val nativeClassFile = extractedClassesDir.get().file("com/microsoft/z3/Native.class").asFile | ||
45 | ClassFilePatcher.removeClassInitializer(nativeClassFile) | ||
46 | } | ||
47 | } | ||
48 | |||
49 | val extractZ3Source by tasks.registering(Sync::class) { | ||
50 | dependsOn(z3Source) | ||
51 | from({ | ||
52 | val zipFile = z3Source.singleFile | ||
53 | zipTree(zipFile).matching { | ||
54 | include("z3-z3-${version}/src/api/java/**/*") | ||
55 | includeEmptyDirs = false | ||
56 | } | ||
57 | }) | ||
58 | eachFile { | ||
59 | val pathInBin = relativePath.segments.drop(4).toTypedArray() | ||
60 | relativePath = RelativePath(true, "com", "microsoft", "z3", *pathInBin) | ||
61 | } | ||
62 | into(extractedSourcesDir) | ||
63 | } | ||
64 | |||
65 | tasks.jar { | ||
66 | // Add class files to our jar manually. | ||
67 | from(extractZ3Jar) | ||
68 | } | ||
69 | |||
70 | tasks.test { | ||
71 | useJUnitPlatform() | ||
72 | } | ||
73 | |||
74 | tasks.named<Jar>("sourcesJar") { | ||
75 | from(extractZ3Source) | ||
76 | } | ||
77 | |||
78 | tasks.named<Javadoc>("javadoc") { | ||
79 | source(sourceSets.main.map { it.allJava }) | ||
80 | source(fileTree(extractedSourcesDir) { | ||
81 | builtBy(extractZ3Source) | ||
82 | include("**/*.java") | ||
83 | }) | ||
84 | options { | ||
85 | this as StandardJavadocDocletOptions | ||
86 | addBooleanOption("Xdoclint:none", true) | ||
87 | // {@code -Xmaxwarns 0} will print all warnings, so we must keep at least one. | ||
88 | addStringOption("Xmaxwarns", "1") | ||
89 | quiet() | ||
90 | } | ||
91 | } | ||
92 | |||
93 | dependencies { | ||
94 | z3("Z3Prover:z3:${version}:${classifier}@zip") | ||
95 | z3Source("Z3Prover:z3:${version}@zip") | ||
96 | // This dependency doesn't get added to Maven metadata, so we have to add the class files to our jar manually. | ||
97 | api(files(extractZ3Jar)) | ||
98 | implementation(libs.jna) | ||
99 | implementation(project(":refinery-z3-solver-darwin-aarch64")) | ||
100 | implementation(project(":refinery-z3-solver-darwin-x86-64")) | ||
101 | implementation(project(":refinery-z3-solver-linux-aarch64")) | ||
102 | implementation(project(":refinery-z3-solver-linux-x86-64")) | ||
103 | implementation(project(":refinery-z3-solver-win32-x86-64")) | ||
104 | testImplementation(libs.junit.api) | ||
105 | testRuntimeOnly(libs.junit.engine) | ||
106 | testRuntimeOnly("org.junit.platform:junit-platform-launcher") | ||
107 | } | ||
diff --git a/z3/subprojects/solver/src/main/java/tools/refinery/z3/Z3SolverLoader.java b/z3/subprojects/solver/src/main/java/tools/refinery/z3/Z3SolverLoader.java new file mode 100644 index 00000000..84f99540 --- /dev/null +++ b/z3/subprojects/solver/src/main/java/tools/refinery/z3/Z3SolverLoader.java | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright 2010-2022 Google LLC | ||
3 | * Copyright 2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: Apache-2.0 | ||
6 | * | ||
7 | * This file is based on | ||
8 | * https://github.com/google/or-tools/blob/f3d1d5f6a67356ec38a7fd2ab607624eea8ad3a6/ortools/java/com/google/ortools/Loader.java | ||
9 | * We adapted the loader logic to extract the JNI libraries of Z3 and the corresponding dependencies instead of the | ||
10 | * Google OR-Tools JNI libraries. | ||
11 | */ | ||
12 | package tools.refinery.z3; | ||
13 | |||
14 | import com.sun.jna.Platform; | ||
15 | |||
16 | import java.io.IOException; | ||
17 | import java.net.URI; | ||
18 | import java.net.URISyntaxException; | ||
19 | import java.nio.file.*; | ||
20 | import java.nio.file.attribute.BasicFileAttributes; | ||
21 | import java.util.Map; | ||
22 | |||
23 | public final class Z3SolverLoader { | ||
24 | private static final String JNI_LIBRARY_NAME = "z3java"; | ||
25 | private static final String SOLVER_LIBRARY_NAME = "z3"; | ||
26 | |||
27 | private static boolean loaded; | ||
28 | |||
29 | private Z3SolverLoader() { | ||
30 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
31 | } | ||
32 | |||
33 | public static synchronized void loadNativeLibraries() { | ||
34 | if (loaded) { | ||
35 | return; | ||
36 | } | ||
37 | try { | ||
38 | System.loadLibrary(getOsSpecificLibraryName(JNI_LIBRARY_NAME)); | ||
39 | loaded = true; | ||
40 | return; | ||
41 | } catch (UnsatisfiedLinkError e) { | ||
42 | // Continue, we'll have to extract the libraries from the classpath. | ||
43 | } | ||
44 | try { | ||
45 | extractAndLoad(); | ||
46 | loaded = true; | ||
47 | } catch (IOException e) { | ||
48 | throw new IllegalStateException("Could not extract and load " + JNI_LIBRARY_NAME, e); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | private static void extractAndLoad() throws IOException { | ||
53 | var resourceName = JNI_LIBRARY_NAME + "-" + Platform.RESOURCE_PREFIX; | ||
54 | var resource = Z3SolverLoader.class.getClassLoader().getResource(resourceName); | ||
55 | if (resource == null) { | ||
56 | throw new IllegalStateException("Resource %s was not found".formatted(resourceName)); | ||
57 | } | ||
58 | URI resourceUri; | ||
59 | try { | ||
60 | resourceUri = resource.toURI(); | ||
61 | } catch (URISyntaxException e) { | ||
62 | throw new IllegalStateException("Invalid resource URI: " + resource); | ||
63 | } | ||
64 | FileSystem fileSystem = null; | ||
65 | boolean newFileSystem = false; | ||
66 | Path extractedPath; | ||
67 | try { | ||
68 | try { | ||
69 | fileSystem = FileSystems.newFileSystem(resourceUri, Map.of()); | ||
70 | newFileSystem = true; | ||
71 | } catch (FileSystemAlreadyExistsException e) { | ||
72 | fileSystem = FileSystems.getFileSystem(resourceUri); | ||
73 | } | ||
74 | var resourcePath = fileSystem.provider().getPath(resourceUri); | ||
75 | if (fileSystem.equals(FileSystems.getDefault())) { | ||
76 | extractedPath = resourcePath; | ||
77 | } else { | ||
78 | extractedPath = extract(resourcePath); | ||
79 | } | ||
80 | } finally { | ||
81 | if (newFileSystem) { | ||
82 | fileSystem.close(); | ||
83 | } | ||
84 | } | ||
85 | // We can't rely on RPATH, so we load libraries in reverse dependency order manually. | ||
86 | try { | ||
87 | loadFromPath(extractedPath, SOLVER_LIBRARY_NAME); | ||
88 | } catch (UnsatisfiedLinkError e) { | ||
89 | if (Platform.isWindows()) { | ||
90 | // Try again with our packaged msvcp140 if the system one is missing. | ||
91 | loadFromPathExactName(extractedPath, "vcruntime140.dll"); | ||
92 | loadFromPathExactName(extractedPath, "vcruntime140_1.dll"); | ||
93 | loadFromPathExactName(extractedPath, "msvcp140.dll"); | ||
94 | loadFromPath(extractedPath, SOLVER_LIBRARY_NAME); | ||
95 | } else { | ||
96 | throw e; | ||
97 | } | ||
98 | } | ||
99 | loadFromPath(extractedPath, JNI_LIBRARY_NAME); | ||
100 | } | ||
101 | |||
102 | private static Path extract(Path resourcePath) throws IOException { | ||
103 | var tempDir = Files.createTempDirectory(JNI_LIBRARY_NAME).toAbsolutePath(); | ||
104 | tempDir.toFile().deleteOnExit(); | ||
105 | Files.walkFileTree(resourcePath, new SimpleFileVisitor<>() { | ||
106 | @Override | ||
107 | public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { | ||
108 | var result = super.preVisitDirectory(dir, attrs); | ||
109 | var targetPath = getTargetPath(dir, resourcePath, tempDir); | ||
110 | if (!Files.exists(targetPath)) { | ||
111 | Files.createDirectory(targetPath); | ||
112 | targetPath.toFile().deleteOnExit(); | ||
113 | } | ||
114 | return result; | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { | ||
119 | var result = super.visitFile(file, attrs); | ||
120 | var targetPath = getTargetPath(file, resourcePath, tempDir); | ||
121 | Files.copy(file, targetPath); | ||
122 | targetPath.toFile().deleteOnExit(); | ||
123 | return result; | ||
124 | } | ||
125 | }); | ||
126 | return tempDir; | ||
127 | } | ||
128 | |||
129 | private static Path getTargetPath(Path sourcePath, Path resourcePath, Path tempDir) { | ||
130 | var targetPath = tempDir.resolve(resourcePath.relativize(sourcePath).toString()).normalize(); | ||
131 | if (!targetPath.startsWith(tempDir)) { | ||
132 | throw new IllegalStateException("Target path '%s' for '%s' is outside '%s'" | ||
133 | .formatted(targetPath, sourcePath, tempDir)); | ||
134 | } | ||
135 | return targetPath; | ||
136 | } | ||
137 | |||
138 | private static String getOsSpecificLibraryName(String libraryName) { | ||
139 | var osSpecificLibraryNamePrefix = Platform.isWindows() ? "lib" : ""; | ||
140 | return osSpecificLibraryNamePrefix + libraryName; | ||
141 | } | ||
142 | |||
143 | private static void loadFromPath(Path extractedPath, String libraryName) { | ||
144 | var osSpecificLibraryName = getOsSpecificLibraryName(libraryName); | ||
145 | loadFromPathExactName(extractedPath, System.mapLibraryName(osSpecificLibraryName)); | ||
146 | } | ||
147 | |||
148 | private static void loadFromPathExactName(Path extractedPath, String exactName) { | ||
149 | var library = extractedPath.resolve(exactName) | ||
150 | .toAbsolutePath() | ||
151 | .toString(); | ||
152 | System.load(library); | ||
153 | } | ||
154 | } | ||
diff --git a/z3/subprojects/solver/src/test/java/tools/refinery/z3/Z3SolverLoaderTest.java b/z3/subprojects/solver/src/test/java/tools/refinery/z3/Z3SolverLoaderTest.java new file mode 100644 index 00000000..df3139cc --- /dev/null +++ b/z3/subprojects/solver/src/test/java/tools/refinery/z3/Z3SolverLoaderTest.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: Apache-2.0 | ||
5 | */ | ||
6 | package tools.refinery.z3; | ||
7 | |||
8 | import com.microsoft.z3.*; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | |||
11 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | ||
12 | import static org.junit.jupiter.api.Assertions.assertEquals; | ||
13 | |||
14 | class Z3SolverLoaderTest { | ||
15 | @Test | ||
16 | void testLoad() { | ||
17 | assertDoesNotThrow(Z3SolverLoader::loadNativeLibraries); | ||
18 | try (var context = new Context()) { | ||
19 | var solver = context.mkSolver(); | ||
20 | var a = context.mkConst("a", context.getIntSort()); | ||
21 | var b = context.mkConst("b", context.getIntSort()); | ||
22 | solver.add(context.mkEq(a, context.mkInt(3))); | ||
23 | solver.add(context.mkEq(b, context.mkMul(context.mkInt(2), a))); | ||
24 | assertEquals(Status.SATISFIABLE, solver.check()); | ||
25 | var model = solver.getModel(); | ||
26 | var bValue = (IntNum) model.getConstInterp(b); | ||
27 | assertEquals(6, bValue.getInt()); | ||
28 | } | ||
29 | } | ||
30 | } | ||