1 module ut.wrap.traits;
2 
3 import test;
4 import xlld.wrap.traits;
5 import xlld.wrap.worksheet;
6 
7 
8 /// return a WorksheetFunction for a double function(double) with no
9 /// optional arguments
10 WorksheetFunction makeWorksheetFunction(wstring name, wstring typeText) @safe pure nothrow {
11     return
12         WorksheetFunction(
13             Procedure(name),
14             TypeText(typeText),
15             FunctionText(name),
16             Optional(
17                 ArgumentText(""w),
18                 MacroType("1"w),
19                 Category(""w),
20                 ShortcutText(""w),
21                 HelpTopic(""w),
22                 FunctionHelp(""w),
23                 ArgumentHelp([]),
24                 )
25             );
26 }
27 
28 ///
29 WorksheetFunction doubleToDoubleFunction(wstring name) @safe pure nothrow {
30     return makeWorksheetFunction(name, "BB"w);
31 }
32 
33 ///
34 WorksheetFunction FP12ToDoubleFunction(wstring name) @safe pure nothrow {
35     return makeWorksheetFunction(name, "BK%"w);
36 }
37 
38 ///
39 WorksheetFunction operToOperFunction(wstring name) @safe pure nothrow {
40     return makeWorksheetFunction(name, "UU"w);
41 }
42 
43 WorksheetFunction asyncFunction(wstring name) @safe pure nothrow {
44     return makeWorksheetFunction(name, ">UX"w);
45 }
46 
47 ///
48 @("getWorksheetFunction for double -> double functions with no extra attributes")
49 @safe pure unittest {
50     extern(Windows) double foo(double) nothrow @nogc { return 0; }
51     getWorksheetFunction!foo.shouldEqual(doubleToDoubleFunction("foo"));
52 
53     extern(Windows) double bar(double) nothrow @nogc { return 0; }
54     getWorksheetFunction!bar.shouldEqual(doubleToDoubleFunction("bar"));
55 }
56 
57 ///
58 @("getWorksheetFunction for double -> int functions should fail")
59 @safe pure unittest {
60     extern(Windows) double foo(int) { return 0; }
61     getWorksheetFunction!foo.shouldThrowWithMessage("Unsupported function type double(int) for foo");
62 }
63 
64 ///
65 @("getworksheetFunction with @Register in order")
66 @safe pure unittest {
67 
68     @Register(ArgumentText("my arg txt"), MacroType("macro"))
69     extern(Windows) double foo(double) nothrow;
70 
71     auto expected = doubleToDoubleFunction("foo");
72     expected.argumentText = ArgumentText("my arg txt");
73     expected.macroType = MacroType("macro");
74 
75     getWorksheetFunction!foo.shouldEqual(expected);
76 }
77 
78 ///
79 @("getworksheetFunction with @Register out of order")
80 @safe pure unittest {
81 
82     @Register(HelpTopic("I need somebody"), ArgumentText("my arg txt"))
83     extern(Windows) double foo(double) nothrow;
84 
85     auto expected = doubleToDoubleFunction("foo");
86     expected.argumentText = ArgumentText("my arg txt");
87     expected.helpTopic = HelpTopic("I need somebody");
88 
89     getWorksheetFunction!foo.shouldEqual(expected);
90 }
91 
92 
93 @safe pure unittest {
94     extern(Windows) double doubleToDouble(double) nothrow;
95     static assert(isWorksheetFunction!doubleToDouble);
96 
97     extern(Windows) LPXLOPER12 operToOper(LPXLOPER12) nothrow;
98     static assert(isWorksheetFunction!operToOper);
99 
100     extern(Windows) void funcAsync(LPXLOPER12 n, LPXLOPER12 asyncHandle) nothrow;
101     static assert(isWorksheetFunction!funcAsync);
102 
103     LPXLOPER12 operToOperWrongLinkage(LPXLOPER12) nothrow;
104     static assert(isWorksheetFunctionModuloLinkage!operToOperWrongLinkage);
105     static assert(!isWorksheetFunction!operToOperWrongLinkage);
106 
107     enum MyEnum { foo, bar, baz, }
108 
109     extern(Windows) MyEnum FuncEnumRet(LPXLOPER12 n) nothrow;
110     static assert(!isWorksheetFunction!FuncEnumRet);
111 
112     extern(Windows) LPXLOPER12 FuncEnumArg(MyEnum _) nothrow;
113     static assert(!isWorksheetFunction!FuncEnumArg);
114 }
115 
116 
117 @("getWorksheetFunctions on test.xl_funcs")
118 @safe pure unittest {
119     getModuleWorksheetFunctions!"test.xl_funcs".shouldEqual(
120         [
121             doubleToDoubleFunction("FuncMulByTwo"),
122             FP12ToDoubleFunction("FuncFP12"),
123             operToOperFunction("FuncFib"),
124             asyncFunction("FuncAsync"),
125         ]
126     );
127 }
128 
129 @("template mixin for getWorkSheetFunctions for test.xl_funcs")
130 unittest {
131     import xlld.wrap.worksheet;
132 
133     // mixin the function here then call it to see if it does what it's supposed to
134     mixin(implGetWorksheetFunctionsString!"test.xl_funcs");
135     getWorksheetFunctions.shouldEqual(
136         [
137             doubleToDoubleFunction("FuncMulByTwo"),
138             FP12ToDoubleFunction("FuncFP12"),
139             operToOperFunction("FuncFib"),
140             asyncFunction("FuncAsync"),
141         ]
142     );
143 }
144 
145 @("implGetWorksheetFunctionsString runtime")
146 unittest {
147     import xlld.wrap.worksheet;
148 
149     // mixin the function here then call it to see if it does what it's supposed to
150     mixin(implGetWorksheetFunctionsString("test.xl_funcs"));
151     getWorksheetFunctions.shouldEqual(
152         [
153             doubleToDoubleFunction("FuncMulByTwo"),
154             FP12ToDoubleFunction("FuncFP12"),
155             operToOperFunction("FuncFib"),
156             asyncFunction("FuncAsync"),
157         ]
158     );
159 }
160 
161 
162 @("worksheet functions to .def file")
163 unittest {
164     dllDefFile!"test.xl_funcs"("myxll32.dll", "Simple D add-in").shouldEqual(
165         DllDefFile(
166             [
167                 Statement("LIBRARY", "myxll32.dll"),
168                 Statement("EXPORTS",
169                           [
170                               "xlAutoOpen",
171                               "xlAutoClose",
172                               "xlAutoFree12",
173                               "FuncMulByTwo",
174                               "FuncFP12",
175                               "FuncFib",
176                               "FuncAsync",
177                           ]),
178             ]
179         )
180     );
181 }
182 
183 
184 @("getTypeText")
185 @safe pure unittest {
186     import std.conv: to; // working around unit-threaded bug
187 
188     double foo(double);
189     getTypeText!foo.to!string.shouldEqual("BB");
190 
191     double bar(FP12*);
192     getTypeText!bar.to!string.shouldEqual("BK%");
193 
194     FP12* baz(FP12*);
195     getTypeText!baz.to!string.shouldEqual("K%K%");
196 
197     FP12* qux(double);
198     getTypeText!qux.to!string.shouldEqual("K%B");
199 
200     LPXLOPER12 fun(LPXLOPER12);
201     getTypeText!fun.to!string.shouldEqual("UU");
202 
203     void void_(LPXLOPER12, LPXLOPER12);
204     getTypeText!void_.to!string.shouldEqual(">UU");
205 
206     @Async
207     void async(LPXLOPER12, LPXLOPER12);
208     getTypeText!async.to!string.shouldEqual(">UX");
209 }