Skip to content
This repository has been archived by the owner on Feb 8, 2022. It is now read-only.

process import statements #65

Closed
wants to merge 8 commits into from
299 changes: 299 additions & 0 deletions Parser.Test/TestParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,305 @@ module Proto2 =
|> should not' (throw typeof<System.FormatException>)

[<Xunit.Trait("Kind", "Unit")>]
module StringImport =

[<Fact>]
let ``Resolve Import Statement`` () =
let files =
[
"test.proto",
"""
syntax = "proto2";

import "import.proto";

message Test {
optional MyEnum a = 1;
}
"""

"import.proto",
"""
enum MyEnum {
DEFAULT = 0;
ONE = 1;
}
"""
] |> Map.ofList

let ast = files |> Parse.loadFromString "test.proto"

ast |> should equal (
[ ("test.proto", [
TSyntax TProto2
TMessage ("Test",
[
TField ("a", TOptional, TIdent("MyEnum"), 1u, [])
])
]);
("import.proto", [
TEnum ("MyEnum",
[
TEnumField ("DEFAULT", 0, [])
TEnumField ("ONE", 1, [])
])
])
])

[<Fact>]
let ``Resolve Recursive Import Statements`` () =
let files =
[
"test.proto",
"""
syntax = "proto2";

import "import.proto";

message Test {
optional MyEnum a = 1;
}
"""
"import.proto",
"""
import "inner.proto";
"""
"inner.proto",
"""
enum MyEnum {
DEFAULT = 0;
ONE = 1;
}
"""
] |> Map.ofList

let ast = files |> Parse.loadFromString "test.proto"

ast |> should equal (
[ ("test.proto", [
TSyntax TProto2
TMessage ("Test",
[
TField ("a", TOptional, TIdent("MyEnum"), 1u, [])
])
]);
("import.proto", []);
("inner.proto", [
TEnum ("MyEnum",
[
TEnumField ("DEFAULT", 0, [])
TEnumField ("ONE", 1, [])
])
])
])

[<Fact>]
let ``Missing import throws`` () =

let files =
[
"test.proto",
"""
import "missing.proto";
"""
] |> Map.ofList

fun () ->
files
|> Parse.loadFromString "test.proto"
|> ignore
|> should throw typeof<System.IO.FileNotFoundException>

[<Fact>]
let ``Resolve Public Import Statement`` () =
let files =
[
"test.proto",
"""
syntax = "proto2";

import public "import.proto";

message Test {
optional MyEnum a = 1;
}
"""
"import.proto",
"""
enum MyEnum {
DEFAULT = 0;
ONE = 1;
}
"""
] |> Map.ofList

let ast = files |> Parse.loadFromString "test.proto"

ast |> should equal (
[ ("test.proto", [
TSyntax TProto2
TEnum ("MyEnum",
[
TEnumField ("DEFAULT", 0, [])
TEnumField ("ONE", 1, [])
])
TMessage ("Test",
[
TField ("a", TOptional, TIdent("MyEnum"), 1u, [])
])
])
])

[<Fact>]
let ``Resolve recursive Public Import Statement`` () =
let files =
[
"test.proto",
"""
syntax = "proto2";

import public "import.proto";

message Test {
optional MyEnum a = 1;
}
"""
"import.proto",
"""
import public "inner.proto";
"""
"inner.proto",
"""
enum MyEnum {
DEFAULT = 0;
ONE = 1;
}
"""
] |> Map.ofList

let ast = files |> Parse.loadFromString "test.proto"

ast |> should equal (
[ ("test.proto", [
TSyntax TProto2
TEnum ("MyEnum",
[
TEnumField ("DEFAULT", 0, [])
TEnumField ("ONE", 1, [])
])
TMessage ("Test",
[
TField ("a", TOptional, TIdent("MyEnum"), 1u, [])
])
])
])

[<Fact>]
let ``Missing public import throws`` () =
let files =
[
"test.proto",
"""
import public "missing.proto";
"""
] |> Map.ofList

fun () ->
files
|> Parse.loadFromString "test.proto"
|> ignore
|> should throw typeof<System.IO.FileNotFoundException>


[<Fact>]
let ``Resolve Weak Import Statement and ignore missing weak import`` () =
let files =
[
"test.proto",
"""
syntax = "proto2";

import weak "import.proto";
import weak "missing.proto";

message Test {
optional MyEnum a = 1;
}
"""
"import.proto",
"""
enum MyEnum {
DEFAULT = 0;
ONE = 1;
}
"""
] |> Map.ofList

let ast = files |> Parse.loadFromString "test.proto"

ast |> should equal (
[ ("test.proto", [
TSyntax TProto2
TMessage ("Test",
[
TField ("a", TOptional, TIdent("MyEnum"), 1u, [])
])
]);
("import.proto", [
TEnum ("MyEnum",
[
TEnumField ("DEFAULT", 0, [])
TEnumField ("ONE", 1, [])
])
])
])


[<Xunit.Trait("Kind", "Unit")>]
module FileImport =

open System
open System.IO

let isMono = System.Type.GetType "Mono.Runtime" |> isNull |> not

/// gets the path for a test file based on the relative path from the executing assembly
let testDir =
let solutionPath =
if isMono then
"../../../"
else
let codeBase = Reflection.Assembly.GetExecutingAssembly().CodeBase
let assemblyPath = DirectoryInfo (Uri codeBase).LocalPath
(assemblyPath.Parent.Parent.Parent.Parent).FullName
Path.Combine(solutionPath, "test")

[<Fact>]
let ``Resolve File Import`` () =
let dirs =
[
testDir
]

let ast =
dirs |> Parse.loadFromFile "riak_kv.proto"

// riak_kv.proto includes riak.proto
ast
|> List.length
|> should equal 2

// riak.proto contains a message definition for RpbGetServerInfoResp
let _, riakAst = ast.[1]
riakAst
|> List.exists(function
| TMessage( "RpbGetServerInfoResp", _ ) -> true
| _ -> false
)
|> should equal true



module RegressionTests =

[<Fact>]
Expand Down
10 changes: 5 additions & 5 deletions Parser/Ast.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ and PStatement =
| TSyntax s -> sprintf "TSyntax %A" s
| TImport (s,v) -> sprintf "TImport (\"%s\",%A)" s v
| TPackage id -> sprintf "TPackage \"%s\"" id
| TOption (n,v) -> sprintf "TOption (%s,%A)" n v
| TOption (n,v) -> sprintf "TOption (\"%s\",%A)" n v
| TMessage (id, xs) ->
sprintf "TMessage (%s,[%s]" id
sprintf "TMessage (\"%s\",[%s]" id
( xs |> List.map (sprintf "%A")
|> List.reduce (sprintf "%s;%s") )
| TEnum (id, xs) -> sprintf "TEnum (%s,%A)" id xs
| TExtend (id,xs) -> sprintf "TEnum (%s,%A)" id xs
| TService (id,xs) -> sprintf "TService (%s,%A)" id xs
| TEnum (id, xs) -> sprintf "TEnum (\"%s\",%A)" id xs
| TExtend (id,xs) -> sprintf "TEnum (\"%s\",%A)" id xs
| TService (id,xs) -> sprintf "TService (\"%s\",%A)" id xs

// TSyntax
and PSyntax =
Expand Down
Loading