Skip to content
This repository was archived by the owner on Dec 23, 2024. It is now read-only.

Commit 93ccbef

Browse files
TIHannosami
authored andcommitted
Added static link tests and extended CompilerAssert (dotnet#8101)
* Changed CompilerAssert to static class. Added Compile/Execute methods that take a Compilation description. Added static link tests * Hiding compilation description internals * Added another test to check for sanity * Making a few optional parameters * Hiding internals of CompilationReference
1 parent 975292a commit 93ccbef

File tree

3 files changed

+438
-55
lines changed

3 files changed

+438
-55
lines changed
+227
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
namespace FSharp.Compiler.UnitTests.CodeGen.EmittedIL
4+
5+
open System.IO
6+
open System.Reflection
7+
open FSharp.Compiler.UnitTests
8+
open NUnit.Framework
9+
10+
[<TestFixture>]
11+
module StaticLinkTests =
12+
13+
[<Test>]
14+
let ``Static link simple library``() =
15+
let module1 =
16+
let source =
17+
"""
18+
module Module1
19+
20+
type C() = class end
21+
"""
22+
Compilation.Create(source, Fsx, Library)
23+
24+
let module2 =
25+
let source =
26+
"""
27+
let y = Module1.C()
28+
printfn "%A" y
29+
"""
30+
Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp(module1, staticLink=true)])
31+
32+
CompilerAssert.Execute(module2,
33+
beforeExecute=(fun _ deps ->
34+
deps
35+
|> List.iter (fun dep -> try File.Delete dep with | _ -> ())))
36+
37+
[<Test>]
38+
let ``Simple exe should fail to execute if dependency was not found and is not statically linked``() =
39+
let module1 =
40+
let source =
41+
"""
42+
module Module1
43+
44+
type C() = class end
45+
"""
46+
Compilation.Create(source, Fsx, Library)
47+
48+
let module2 =
49+
let source =
50+
"""
51+
let y = Module1.C()
52+
printfn "%A" y
53+
"""
54+
Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp module1])
55+
56+
Assert.Throws<TargetInvocationException>(fun _ ->
57+
CompilerAssert.Execute(module2,
58+
beforeExecute=(fun _ deps ->
59+
deps
60+
|> List.iter (fun dep -> try File.Delete dep with | _ -> ())))) |> ignore
61+
62+
[<Test>]
63+
let ``Simple exe should execute if dependency was found and is not statically linked``() =
64+
let module1 =
65+
let source =
66+
"""
67+
module Module1
68+
69+
type C() = class end
70+
"""
71+
Compilation.Create(source, Fsx, Library)
72+
73+
let module2 =
74+
let source =
75+
"""
76+
let y = Module1.C()
77+
printfn "%A" y
78+
"""
79+
Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp module1])
80+
81+
CompilerAssert.Execute module2
82+
83+
[<Test>]
84+
let ``Static link quotes in multiple modules``() =
85+
let module1 =
86+
let source =
87+
"""
88+
module Module1
89+
90+
module Test =
91+
let inline run() =
92+
<@ fun (output:'T[]) (input:'T[]) (length:int) ->
93+
let start = 0
94+
let mutable i = start
95+
while i < length do
96+
output.[i] <- input.[i]
97+
i <- i + 1 @>
98+
99+
let bar() =
100+
sprintf "%A" (run())
101+
102+
type C() =
103+
104+
[<ReflectedDefinition>]
105+
static member F x = (C(), System.DateTime.Now)
106+
"""
107+
Compilation.Create(source, Fsx, Library)
108+
109+
let module2 =
110+
let source =
111+
"""
112+
113+
let a = Module1.Test.bar()
114+
let b = sprintf "%A" (Module1.Test.run())
115+
116+
let test1 = (a=b)
117+
type D() =
118+
119+
[<ReflectedDefinition>]
120+
static member F x = (Module1.C(), D(), System.DateTime.Now)
121+
122+
123+
let z2 = Quotations.Expr.TryGetReflectedDefinition(typeof<Module1.C>.GetMethod("F"))
124+
let s2 = (sprintf "%2000A" z2)
125+
let test2 = (s2 = "Some Lambda (x, NewTuple (NewObject (C), PropertyGet (None, Now, [])))")
126+
127+
let z3 = Quotations.Expr.TryGetReflectedDefinition(typeof<D>.GetMethod("F"))
128+
let s3 = (sprintf "%2000A" z3)
129+
let test3 = (s3 = "Some Lambda (x, NewTuple (NewObject (C), NewObject (D), PropertyGet (None, Now, [])))")
130+
131+
#if EXTRAS
132+
// Add some references to System.ValueTuple, and add a test case which statically links this DLL
133+
let test4 = struct (3,4)
134+
let test5 = struct (z2,z3)
135+
#endif
136+
137+
if not test1 then
138+
stdout.WriteLine "*** test1 FAILED";
139+
eprintf "FAILED, in-module result %s is different from out-module call %s" a b
140+
141+
if not test2 then
142+
stdout.WriteLine "*** test2 FAILED";
143+
eprintf "FAILED, %s is different from expected" s2
144+
if not test3 then
145+
stdout.WriteLine "*** test3 FAILED";
146+
eprintf "FAILED, %s is different from expected" s3
147+
148+
149+
if test1 && test2 && test3 then ()
150+
else failwith "Test Failed"
151+
"""
152+
Compilation.Create(source, Fsx, Exe, cmplRefs=[CompilationReference.CreateFSharp(module1, staticLink=true)])
153+
154+
CompilerAssert.Execute(module2, ignoreWarnings=true)
155+
156+
[<Test>]
157+
let ``Static link quotes in multiple modules - optimized``() =
158+
let module1 =
159+
let source =
160+
"""
161+
module Module1
162+
163+
module Test =
164+
let inline run() =
165+
<@ fun (output:'T[]) (input:'T[]) (length:int) ->
166+
let start = 0
167+
let mutable i = start
168+
while i < length do
169+
output.[i] <- input.[i]
170+
i <- i + 1 @>
171+
172+
let bar() =
173+
sprintf "%A" (run())
174+
175+
type C() =
176+
177+
[<ReflectedDefinition>]
178+
static member F x = (C(), System.DateTime.Now)
179+
"""
180+
Compilation.Create(source, Fsx, Library, [|"--optimize+"|])
181+
182+
let module2 =
183+
let source =
184+
"""
185+
186+
let a = Module1.Test.bar()
187+
let b = sprintf "%A" (Module1.Test.run())
188+
189+
let test1 = (a=b)
190+
type D() =
191+
192+
[<ReflectedDefinition>]
193+
static member F x = (Module1.C(), D(), System.DateTime.Now)
194+
195+
196+
let z2 = Quotations.Expr.TryGetReflectedDefinition(typeof<Module1.C>.GetMethod("F"))
197+
let s2 = (sprintf "%2000A" z2)
198+
let test2 = (s2 = "Some Lambda (x, NewTuple (NewObject (C), PropertyGet (None, Now, [])))")
199+
200+
let z3 = Quotations.Expr.TryGetReflectedDefinition(typeof<D>.GetMethod("F"))
201+
let s3 = (sprintf "%2000A" z3)
202+
let test3 = (s3 = "Some Lambda (x, NewTuple (NewObject (C), NewObject (D), PropertyGet (None, Now, [])))")
203+
204+
#if EXTRAS
205+
// Add some references to System.ValueTuple, and add a test case which statically links this DLL
206+
let test4 = struct (3,4)
207+
let test5 = struct (z2,z3)
208+
#endif
209+
210+
if not test1 then
211+
stdout.WriteLine "*** test1 FAILED";
212+
eprintf "FAILED, in-module result %s is different from out-module call %s" a b
213+
214+
if not test2 then
215+
stdout.WriteLine "*** test2 FAILED";
216+
eprintf "FAILED, %s is different from expected" s2
217+
if not test3 then
218+
stdout.WriteLine "*** test3 FAILED";
219+
eprintf "FAILED, %s is different from expected" s3
220+
221+
222+
if test1 && test2 && test3 then ()
223+
else failwith "Test Failed"
224+
"""
225+
Compilation.Create(source, Fsx, Exe, [|"--optimize+"|], [CompilationReference.CreateFSharp(module1, staticLink=true)])
226+
227+
CompilerAssert.Execute(module2, ignoreWarnings=true)

0 commit comments

Comments
 (0)