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