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