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