Skip to content

Commit

Permalink
Implement BindgenReportingSpec
Browse files Browse the repository at this point in the history
  • Loading branch information
kornilova203 committed Jul 16, 2018
1 parent ff5491e commit 0048a24
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 78 deletions.
90 changes: 50 additions & 40 deletions bindgen/ir/IR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,63 +101,73 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {

std::string objectName = handleReservedWords(ir.objectName);

if (!ir.libObjEmpty()) {
bool isLibObjectEmpty = ir.libObjEmpty();

if (!isLibObjectEmpty) {
if (!ir.linkName.empty()) {
s << "@native.link(\"" << ir.linkName << "\")\n";
}

s << "@native.extern\n"
<< "object " << objectName << " {\n";
}

for (const auto &typeDef : ir.typeDefs) {
if (ir.shouldOutput(typeDef)) {
s << *typeDef;
if (typeDef->getType()) {
auto *structOrUnion =
dynamic_cast<StructOrUnion *>(typeDef->getType().get());
if (structOrUnion &&
structOrUnion->hasIllegalUsageOfOpaqueType()) {
llvm::errs()
<< "Error: record " << structOrUnion->getName()
<< " has field of incomplete type. Declarations "
"that use this type may not work properly.\n";
llvm::errs().flush();
}
for (const auto &typeDef : ir.typeDefs) {
if (ir.shouldOutput(typeDef)) {
s << *typeDef;
if (typeDef->getType()) {
auto *structOrUnion =
dynamic_cast<StructOrUnion *>(typeDef->getType().get());
if (structOrUnion &&
structOrUnion->hasIllegalUsageOfOpaqueType()) {
llvm::errs()
<< "Error: record " << structOrUnion->getName()
<< " has field of incomplete type. Declarations "
"that use this type may not work properly.\n";
llvm::errs().flush();
}
}
} else if (isAliasForOpaqueType(typeDef.get()) &&
ir.inMainFile(*typeDef)) {
llvm::errs() << "Warning: type alias " + typeDef->getName()
<< " is skipped because it is unused alias for "
"incomplete type."
<< "\n";
llvm::errs().flush();
}
}

for (const auto &variable : ir.variables) {
if (!variable->hasIllegalUsageOfOpaqueType()) {
s << *variable;
} else {
llvm::errs() << "Error: Variable " << variable->getName()
<< " is skipped because it has incomplete type.\n";
}
for (const auto &variable : ir.variables) {
if (!variable->hasIllegalUsageOfOpaqueType()) {
s << *variable;
} else {
llvm::errs() << "Error: Variable " << variable->getName()
<< " is skipped because it has incomplete type.\n";
}
}

for (const auto &varDefine : ir.varDefines) {
if (!varDefine->hasIllegalUsageOfOpaqueType()) {
s << *varDefine;
} else {
llvm::errs() << "Error: Variable alias " << varDefine->getName()
<< " is skipped because it has incomplete type\n";
llvm::errs().flush();
}
for (const auto &varDefine : ir.varDefines) {
if (!varDefine->hasIllegalUsageOfOpaqueType()) {
s << *varDefine;
} else {
llvm::errs() << "Error: Variable alias " << varDefine->getName()
<< " is skipped because it has incomplete type.\n";
llvm::errs().flush();
}
}

for (const auto &func : ir.functions) {
if (!func->isLegalScalaNativeFunction()) {
llvm::errs()
<< "Warning: Function " << func->getName()
<< " is skipped because Scala Native does not support "
"passing structs and arrays by value.\n";
llvm::errs().flush();
} else {
s << *func;
}
for (const auto &func : ir.functions) {
if (!func->isLegalScalaNativeFunction()) {
llvm::errs() << "Warning: Function " << func->getName()
<< " is skipped because Scala Native does not support "
"passing structs and arrays by value.\n";
llvm::errs().flush();
} else {
s << *func;
}
}

if (!isLibObjectEmpty) {
s << "}\n\n";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.scalanative.bindgen

import java.io.{File, PrintWriter}

import org.scalatest.FunSpec

class BindgenReportingSpec extends FunSpec {
describe("Bindgen") {

val bindgenPath = System.getProperty("bindgen.path")

def writeToFile(file: File, input: String): Unit = {
new PrintWriter(file) {
try {
write(input)
} finally {
close()
}
}
}

def bindgen(input: String): Bindings = {
val tempFile = File.createTempFile("scala-native-bindgen-tests", ".h")
try {
writeToFile(tempFile, input)

Bindgen()
.bindgenExecutable(new File(bindgenPath))
.header(tempFile)
.name("BindgenTests")
.link("bindgentests")
.packageName("org.scalanative.bindgen.samples")
.excludePrefix("__")
.generate()

} finally {
tempFile.delete()
}
}

it("Skips variable with opaque type") {
val bindings =
bindgen(input = """struct undefinedStruct;
|extern struct undefinedStruct removedExtern;
|#define removedExternAlias removedExtern
|""".stripMargin)
assert(
bindings.errs == """Error: Variable removedExtern is skipped because it has incomplete type.
|Error: Variable alias removedExternAlias is skipped because it has incomplete type.""".stripMargin)

}

it("Skips function that has parameter of opaque type") {
val bindings =
bindgen(input = """struct undefinedStruct;
|void useUndefinedStruct(struct undefinedStruct);
|""".stripMargin)
assert(
bindings.errs == "Warning: Function useUndefinedStruct is skipped because Scala Native does not " +
"support passing structs and arrays by value.")
}

it("Skips function that has return value of opaque type") {
val bindings =
bindgen(input = """struct undefinedStruct;
|typedef struct undefinedStruct aliasForUndefinedStruct;
|aliasForUndefinedStruct returnUndefinedStruct();
|""".stripMargin)
assert(
bindings.errs == "Warning: Function returnUndefinedStruct is skipped because Scala Native does not " +
"support passing structs and arrays by value.")
}

it("Skips unused alias for opaque type") {
val bindings =
bindgen(input = """union undefinedUnion;
|typedef union undefinedUnion aliasForUndefinedUnion;
|""".stripMargin)
assert(
bindings.errs == "Warning: type alias aliasForUndefinedUnion is skipped because it is unused alias for incomplete type.")
}
}
}
42 changes: 4 additions & 38 deletions tests/src/test/scala/org/scalanative/bindgen/BindgenSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,16 @@ class BindgenSpec extends FunSpec {
assert(new File(bindgenPath).exists, s"$bindgenPath does not exist")
}

/**
* @return errors
*/
def bindgen(inputFile: File,
name: String,
outputFile: Option[File] = None): String = {
val bindings = Bindgen()
def bindgen(inputFile: File, name: String, outputFile: File): Unit = {
Bindgen()
.bindgenExecutable(new File(bindgenPath))
.header(inputFile)
.name(name)
.link("bindgentests")
.packageName("org.scalanative.bindgen.samples")
.excludePrefix("__")
.generate()

if (outputFile.isDefined) {
bindings.writeToFile(outputFile.get)
}

bindings.errs
.writeToFile(outputFile)
}

def contentOf(file: File) =
Expand All @@ -48,35 +38,11 @@ class BindgenSpec extends FunSpec {
val expected = new File(inputDirectory, testName + ".scala")
val output = new File(outputDir, testName + ".scala")

bindgen(input, testName, Option(output))
bindgen(input, testName, output)

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

it(s"should print correct warnings for ${input.getName}") {
val testName = input.getName.replace(".h", "")

val errs = bindgen(input, testName)

testName match {
case "LiteralDefine" =>
assert(
errs == "Warning: integer value does not fit into 8 bytes: 18446744073709551615\n" +
"Warning: integer value does not fit into 8 bytes: 9223372036854775809")
case "OpaqueTypes" =>
assert(
errs == "Error: Variable removedExtern is skipped because it has incomplete type.\n" +
"Error: Variable alias removedExternAlias is skipped because it has incomplete type\n" +
"Warning: Function useUndefinedStruct is skipped because Scala Native does not support passing structs and arrays by value.")
case "Function" =>
assert(
errs == "Warning: Function acceptsStructValue is skipped because Scala Native does not support passing structs and arrays by value.\n" +
"Warning: Function returnsStructValue is skipped because Scala Native does not support passing structs and arrays by value.\n" +
"Warning: Function acceptsUnionValue is skipped because Scala Native does not support passing structs and arrays by value.")
case _ => assert(errs == "")
}
}
}
}
}

0 comments on commit 0048a24

Please sign in to comment.