Skip to content

Migrating tests to Scala #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
target
target/
12 changes: 6 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ sudo: required
compiler: gcc

script:
- docker-compose build ubuntu-16.04-llvm-$LLVM_VERSION
- docker run --rm -ti scala-native-bindgen:ubuntu-16.04-llvm-$LLVM_VERSION /usr/include/ctype.h -name ctype --
- docker run --rm -ti --entrypoint /src/target/scalaBindgenTest scala-native-bindgen:ubuntu-16.04-llvm-$LLVM_VERSION
- docker-compose build $TEST_ENV
- docker run --rm -ti scala-native-bindgen:$TEST_ENV /usr/include/ctype.h -name ctype --
- docker-compose run --rm sbt-test

matrix:
include:
- env: LLVM_VERSION=dev
- env: LLVM_VERSION=6.0
- env: LLVM_VERSION=5.0
- env: TEST_ENV=ubuntu-16.04-llvm-dev
- env: TEST_ENV=ubuntu-16.04-llvm-6.0
- env: TEST_ENV=ubuntu-16.04-llvm-5.0
8 changes: 6 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ FROM ubuntu:$UBUNTU_VERSION

RUN set -x \
&& apt update \
&& apt install -y curl build-essential \
&& apt install -y apt-transport-https \
&& echo "deb https://dl.bintray.com/sbt/debian /" > /etc/apt/sources.list.d/sbt.list \
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 \
&& apt update \
&& apt install -y curl build-essential openjdk-8-jdk-headless sbt \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /cmake
Expand All @@ -20,7 +24,7 @@ ARG LLVM_DEB_COMPONENT=-$LLVM_VERSION
RUN set -x \
&& curl https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - \
&& . /etc/lsb-release \
&& echo "deb http://apt.llvm.org/$DISTRIB_CODENAME/ llvm-toolchain-$DISTRIB_CODENAME$LLVM_DEB_COMPONENT main" > /etc/apt/sources.list.d/llvm.list \
&& echo "deb https://apt.llvm.org/$DISTRIB_CODENAME/ llvm-toolchain-$DISTRIB_CODENAME$LLVM_DEB_COMPONENT main" > /etc/apt/sources.list.d/llvm.list \
&& apt update \
&& apt install -y clang-$LLVM_VERSION libclang-$LLVM_VERSION-dev make \
&& rm -rf /var/lib/apt/lists/*
Expand Down
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,30 @@ Running the previous command wild also yield warnings along with the translation

## Building

Building this tool requires LLVM and Clang. Ensure that `llvm-config` is in your path.
Building this tool requires [CMake], [LLVM] and [Clang]. See the [Scala
Native setup guide] for instructions on installing the dependencies.

```sh
# Validate LLVM installation
llvm-config --version --cmakedir --cxxflags --ldflags

mkdir -p target
cd target
cmake ..
make
./scalaBindgen /usr/include/ctype.h -name ctype
./scalaBindgen /usr/include/ctype.h -name ctype --
```

[CMake]: https://cmake.org/
[LLVM]: https://llvm.org/
[Clang]: https://clang.llvm.org/
[Scala Native setup guide]: http://www.scala-native.org/en/latest/user/setup.html

## Testing

The tests assumes that the above instructions for building has been
followed.

```sh
cd tests
sbt test
```

## License
Expand Down
11 changes: 11 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,14 @@ services:
- UBUNTU_VERSION=16.04
- LLVM_VERSION=5.0

sbt-test:
image: scala-native-bindgen:${TEST_ENV}
entrypoint:
- sh
- -c
- |
cd /src/tests
sbt compile test
volumes:
- ${HOME}/.ivy2:/root/.ivy2
- ${HOME}/.sbt:/root/.sbt
29 changes: 29 additions & 0 deletions tests/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
inThisBuild(
Def.settings(
organization := "org.scalanative.bindgen",
version := "0.1-SNAPSHOT",
scalaVersion := "2.11.12",
scalacOptions ++= Seq(
"-deprecation",
"-unchecked",
"-feature",
"-encoding",
"utf8"
)
))

val `scala-native-bindgen-tests` = project
.in(file("."))
.settings(
fork in Test := true,
javaOptions in Test += "-Dbindgen.path=" + file("../target/scalaBindgen"),
watchSources += WatchSource(
baseDirectory.value / "samples",
"*.h" || "*.scala",
NothingFilter
),
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % Test
)

val samples = project
.enablePlugins(ScalaNativePlugin)
1 change: 1 addition & 0 deletions tests/project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.1.6
1 change: 1 addition & 0 deletions tests/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.3.7")
6 changes: 6 additions & 0 deletions tests/samples/Function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
int no_args();
int void_arg(void);
void one_arg(int a);
void *two_args(float a, int b);
void anonymous_args(float, int);
double variadic_args(double a, void* b, ...);
14 changes: 14 additions & 0 deletions tests/samples/Function.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import scala.scalanative._
import scala.scalanative.native._
import scala.scalanative.native.Nat._

@native.link("Function")
@native.extern
object Function {
def no_args(): native.CInt = native.extern
def void_arg(): native.CInt = native.extern
def one_arg(a: native.CInt): Unit = native.extern
def two_args(a: native.CFloat, b: native.CInt): native.Ptr[Byte] = native.extern
def anonymous_args(anonymous0: native.CFloat, anonymous1: native.CInt): Unit = native.extern
def variadic_args(a: native.CDouble, b: native.Ptr[Byte], varArgs: native.CVararg*): native.CDouble = native.extern
}
36 changes: 36 additions & 0 deletions tests/samples/NativeTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Until generated type aliases are pruned the following dummy typedefs
* are here to avoid including standard headers:
*
* #include <stddef.h>
* #include <uchar.h>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workaround until #13 is fixed.

*/
typedef unsigned int size_t;
typedef unsigned int ptrdiff_t;
typedef unsigned short char16_t;
typedef unsigned int char32_t;

typedef void void_type;
typedef char char_type;
typedef signed char signed_char_type;
typedef unsigned char unsigned_char_type;
typedef short short_type;
typedef unsigned short unsigned_short_type;
typedef int int_type;
typedef unsigned int unsigned_int_type;
typedef long long_type;
typedef long int long_int_type;
typedef unsigned long unsigned_long_type;
typedef unsigned long int unsigned_long_int_type;
typedef long long long_long_type;
typedef unsigned long long unsigned_long_long_type;
typedef float float_type;
typedef double double_type;
typedef void * ptr_byte_type;
typedef int * ptr_int_type;
typedef char * cstring_type;

typedef size_t size_t_type;
typedef ptrdiff_t ptrdiff_t_type;
typedef char16_t char16_t_type;
typedef char32_t char32_t_type;
35 changes: 35 additions & 0 deletions tests/samples/NativeTypes.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import scala.scalanative._
import scala.scalanative.native._
import scala.scalanative.native.Nat._

@native.link("NativeTypes")
@native.extern
object NativeTypes {
type size_t = native.CUnsignedInt
type ptrdiff_t = native.CUnsignedInt
type char16_t = native.CUnsignedShort
type char32_t = native.CUnsignedInt
type void_type = Unit
type char_type = native.CChar
type signed_char_type = native.CSignedChar
type unsigned_char_type = native.CUnsignedChar
type short_type = native.CShort
type unsigned_short_type = native.CUnsignedShort
type int_type = native.CInt
type unsigned_int_type = native.CUnsignedInt
type long_type = native.CLong
type long_int_type = native.CLong
type unsigned_long_type = native.CUnsignedLong
type unsigned_long_int_type = native.CUnsignedLong
type long_long_type = native.CLongLong
type unsigned_long_long_type = native.CUnsignedLongLong
type float_type = native.CFloat
type double_type = native.CDouble
type ptr_byte_type = native.Ptr[Byte]
type ptr_int_type = native.Ptr[native.CInt]
type cstring_type = native.CString
type size_t_type = native.CSize
type ptrdiff_t_type = native.CPtrDiff
type char16_t_type = native.CChar16
type char32_t_type = native.CChar32
}
6 changes: 6 additions & 0 deletions tests/samples/Struct.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
struct point {
int x;
int y;
};

typedef struct point *point_s;
24 changes: 24 additions & 0 deletions tests/samples/Struct.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import scala.scalanative._
import scala.scalanative.native._
import scala.scalanative.native.Nat._

@native.link("Struct")
@native.extern
object Struct {
type struct_point = native.CStruct2[native.CInt, native.CInt]
type point_s = native.Ptr[struct_point]
}

import Struct._

object StructHelpers {
implicit class struct_point_ops(val p: native.Ptr[struct_point]) extends AnyVal {
def x: native.CInt = !p._1
def x_=(value: native.CInt):Unit = !p._1 = value
def y: native.CInt = !p._2
def y_=(value: native.CInt):Unit = !p._2 = value
}

def struct_point()(implicit z: native.Zone): native.Ptr[struct_point] = native.alloc[struct_point]

}
18 changes: 18 additions & 0 deletions tests/samples/Typedef.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
enum days {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY,
};

typedef enum {
OFF,
ON
} toggle_e;

typedef int (*int2int)(int);
typedef const char * (*day2string)(enum days);
typedef void (*toggle)(toggle_e state);
28 changes: 28 additions & 0 deletions tests/samples/Typedef.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import scala.scalanative._
import scala.scalanative.native._
import scala.scalanative.native.Nat._

@native.link("Typedef")
@native.extern
object Typedef {
type enum_days = native.CInt
type enum_toggle_e = native.CInt
type toggle_e = enum_toggle_e
type int2int = native.CFunctionPtr1[native.CInt, native.CInt]
type day2string = native.CFunctionPtr1[enum_days, native.CString]
type toggle = native.CFunctionPtr1[toggle_e, Unit]
}

import Typedef._

object TypedefEnums {
final val enum_days_MONDAY = 0
final val enum_days_TUESDAY = 1
final val enum_days_WEDNESDAY = 2
final val enum_days_THURSDAY = 3
final val enum_days_FRIDAY = 4
final val enum_days_SATURDAY = 5
final val enum_days_SUNDAY = 6
final val enum_toggle_e_OFF = 0
final val enum_toggle_e_ON = 1
}
53 changes: 53 additions & 0 deletions tests/src/test/scala/org/scalanative/bindgen/BindgenSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.scalanative.bindgen

import java.io.{File, PrintWriter}
import org.scalatest.FunSpec
import scala.io.Source
import scala.sys.process._

class BindgenSpec extends FunSpec {
describe("Bindgen") {
val bindgenPath = System.getProperty("bindgen.path")
val inputDirectory = new File("samples")

val outputDir = new File("target/bindgen-samples")
Option(outputDir.listFiles()).foreach(_.foreach(_.delete()))
outputDir.mkdirs()

it("should exist") {
assert(new File(bindgenPath).exists)
}

def bindgen(inputFile: File, name: String, outputFile: File): Unit = {
val cmd = Seq(
bindgenPath,
inputFile.getAbsolutePath,
"-name",
name,
"--"
)
val output = Process(cmd).lineStream.mkString("\n")

new PrintWriter(outputFile) {
write(output)
close()
}
}

def contentOf(file: File) =
Source.fromFile(file).getLines.mkString("\n").trim()

for (input <- inputDirectory.listFiles() if input.getName.endsWith(".h")) {
it(s"should generate bindings for ${input.getName}") {
val testName = input.getName.replace(".h", "")
val expected = new File(inputDirectory, testName + ".scala")
val output = new File(outputDir, testName + ".scala")

bindgen(input, testName, output)

assert(output.exists())
assert(contentOf(output) == contentOf(expected))
}
}
}
}