Initial merge-commit of the OIC code. Should successfully do discovery for single...
[platform/upstream/iotivity.git] / examples / test_properties.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation All Rights Reserved.
4 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
5
6 /* To avoid confusion: These are not unit tests, these are "test programs". */
7
8 #include <map>
9 #include <string>
10 #include <cassert>
11 #include <cstring>
12 #include <cstdlib>
13 #include <iostream>
14 #include <algorithm>
15 #include <stdexcept>
16
17 #include "OCReflect.h"
18
19 using namespace OC::OCReflect;
20
21 // Convert a native type to a property:
22 void convert_test()
23 {
24  using std::cout;
25  using namespace OC::OCReflect;
26 /*
27  // Nil (JSON: null):
28  {
29     property_signature ps(property_type::nil);
30     named_property_binding npb("nil_property", ps); 
31  }
32 */
33
34  // Boolean:
35  {
36     OC::OCReflect::property my_bool     = OC::OCReflect::make_property::apply(true, "my_bool");
37     OC::OCReflect::property my_bool_too = make_property::apply(false, "my_bool_too");
38
39     cout << my_bool << '\n' << my_bool_too << '\n';
40
41     auto x = concretize<bool>(my_bool);
42     auto y = concretize<bool>(my_bool_too);
43
44     cout << "got back: " << x << '\n';
45     cout << "got back: " << y << '\n';
46
47         assert(x == true);
48         assert(y == false);
49  }
50
51  // Integer:
52  {
53     const int64_t input { 1024 };
54     auto my_int = make_property::apply(input, "my int");
55
56     cout << my_int << '\n';
57
58     auto x = concretize<int64_t>(my_int);
59
60     cout << x << '\n';
61
62         assert(input == x);
63  }
64
65  // Rational (JSON: number):
66  {
67         const double input { 1024.0 };
68         auto my_float = make_property::apply(input, "my float");
69
70         cout << my_float << '\n';
71
72         auto x = concretize<double>(my_float);
73
74         cout << x << '\n';
75
76         assert(input == x);
77  }
78
79  // String:
80  {
81         const std::string input { "Hello, World!" };
82
83         auto my_string = make_property::apply(input, "my string");
84
85         cout << my_string << '\n';
86
87         auto x = concretize<std::string>(my_string);
88
89         cout << x << '\n';
90
91         assert(input == x);
92  }
93
94 /*
95  // List (JSON: array):
96  {
97     property_signature(property_type::list);    
98  }
99 */
100 /* JFW:
101  // Dictionary (JSON: object):
102  {
103     property_signature(property_type::dictionary);  
104  }
105 */
106
107  // test with attributes:
108 }
109
110 typedef property return_property;
111
112 template <class InT>
113 return_property make_return_property(const InT& in)
114 {
115  return OC::OCReflect::make_property::apply(in, "__RETURN_VALUE__"); // ugly-- avert your eyes!
116 }
117
118 typedef std::function<return_property(const property_vector&)>  bound_call;
119
120 struct server
121 {
122  std::map<std::string, bound_call>      methods;
123 };
124
125 std::string test_fn(const std::string s0, const std::string s1)
126 {
127  return s0 + " " + s1;
128 }
129
130 /*
131 template <class ...ParamsT>
132 void check_signature(const property_signature_vector& param_types, ParamsT ...params)
133 {
134  
135 }
136
137 struct call
138 {
139  template <class ...ParamsT>
140  static return_property operator()(bound_call& f, const property_signature return_type, const property_signature_vector& param_types, ParamsT ...params)
141  {
142         check_signature(param_types, params...);
143
144         auto result = f(params...);
145
146         check_signature(return_type, result);
147
148         return result;
149  }
150 */
151
152 /* - match type
153    - if type is concrete type
154    - return curried function for that thing
155    - this binds eventually to property(property_list), but calls underlying fn
156 */
157
158 OC::OCReflect::property_signature head(const OC::OCReflect::property_signature_vector& psv)
159 {
160  return psv[0];
161 }
162
163 // sloooow, but it will suit our purpose:
164 OC::OCReflect::property_signature_vector tail(const OC::OCReflect::property_signature_vector psv)
165 {
166  return OC::OCReflect::property_signature_vector(1 + psv.begin(), psv.end());
167 }
168
169 bool type_matches(const OC::OCReflect::property_type& expected_pt, const OC::OCReflect::property_data& in)
170 {
171  auto begin = in.begin();
172  
173  auto found_pt = static_cast<OC::OCReflect::property_type>(*begin);
174
175  std::cout << "val ept=" << (int)expected_pt << ", ept: " << (int)found_pt << '\n';
176
177  return expected_pt == found_pt;
178 }
179
180 bool type_matches(const OC::OCReflect::property_type expected_pt, const OC::OCReflect::property& in)
181 {
182  return type_matches(expected_pt, std::get<1>(in));
183 }
184
185 bool signature_matches(const OC::OCReflect::property_signature&)
186 {
187  return true;
188 }
189
190 /* JFW: tmp
191 template <class X>
192 bool signature_matches(const OC::OCReflect::property_signature& expected, X x)
193 {
194  return type_matches(expected.type, OC::OCReflect::make_property::apply(x, "_")); 
195 }
196
197 template <class X, class ...XS>
198 bool signature_matches(const OC::OCReflect::property_signature_vector expected, X x, XS ...xs)
199 {
200  return signature_matches(head(expected), x) && signature_matches(tail(expected), xs...);
201 }
202
203 template <class ...XS>
204 bool signature_matches(const OC::OCReflect::property_signature_vector expected, XS ...xs)
205 {
206  return signature_matches(head(expected), x) && signature_matches(tail(expected), xs...);
207  // return signature_matches(expected, xs...);
208 }
209 */
210
211 void call_test()
212 {
213  server s;
214
215  s.methods["test_fn"] = 
216         [](const property_vector& in) -> return_property
217         {
218                  for(const auto& p : in)
219                  std::cout << p << '\n'; 
220
221                 auto s0 = concretize<std::string>(in[0]);
222                 auto s1 = concretize<std::string>(in[1]);
223
224                 return make_return_property(test_fn(s0, s1));
225         };
226
227  property_vector pv;
228  pv.emplace_back(make_property::apply("Hello", "s0"));
229  pv.emplace_back(make_property::apply("World", "s1"));
230
231  std::cout << "INPUT:\n" << pv << '\n';
232
233  auto result = s.methods["test_fn"](pv);
234
235  std::cout << concretize<std::string>(std::get<1>(result));
236
237  using namespace OC::OCReflect;
238
239  // typechecking:
240  {
241  auto foo = make_property::apply("Hi there", "s0");
242  assert(false == type_matches(property_type::boolean, foo));
243  assert(true == type_matches(property_type::string, foo));
244  }
245
246 /* JFW: tmp
247  // signature typechecking:
248  {
249         property_signature_vector sig {
250                 { property_type::string },
251                 { property_type::integer }
252         };
253
254         assert(false == signature_matches(sig, 5, "Hello"));
255         assert(true == signature_matches(sig, "Hello", 5));
256  }
257 */
258
259 /*
260  auto sig = make_fun_sig(property_type::string,                 // result
261                                                  property_type::string, property_type::string); // params
262  std::cout << sig << '\n';
263 */
264 /*
265  auto f = make_fun(test_fn, 
266                                    property_type::string,                                                 // result
267                                    property_type::string, property_type::string); // params
268 */
269 }
270
271 // Demo of how to generate OCStack stuff:
272 void rep_test()
273 {
274  using OC::OCReflect::property_type;
275  using OC::OCReflect::named_property_binding;
276
277  named_property_binding_vector sigs {
278         named_property_binding("state", property_type::boolean),
279         named_property_binding("power", property_type::integer)
280  };
281
282  using namespace OC::OCReflect::to_OCStack;
283
284  /* JFW: note:
285  char *LEDrep[] = { "state;b", "power;i", NULL};
286
287  char **LEDrep = convert(convert(sigs));
288
289  if(0 == LEDrep)
290   error();
291
292  CREATE_RESOURCE_TYPE(LED, "core.led", LEDrep);
293  */
294 std::vector<std::string> reps { convert(sigs) }; 
295  for(const auto& r : reps)
296   std::cout << r << '\n';
297
298  // Example of flattening to a single string:
299  char *flattened = flatten(reps);
300  std::cout << "FLATTENED: " << flattened << '\n';
301
302  // Example of converting to an array of char*s:
303  char **handle = convert(reps); 
304
305  if(nullptr == handle)
306   throw std::runtime_error("handle is a nullptr");
307
308  std::for_each(handle, handle + length(handle), [](const char *s) { std::cout << s << '\n'; });
309
310  /* ...or, you could do it this way (sad panda!):
311  for(char **cursor = handle; nullptr != *cursor; ++cursor)
312   printf("%s\n", *cursor);
313  */
314
315  release(handle); // remember to free the memory!
316 }
317
318 void from_rep_test()
319 {
320  using std::cout;
321
322  std::cout << "from_rep_test() doesn't do much yet :-)\n";
323 /*
324  const char *LEDrep[] = { "state;b", "power;i", NULL };
325
326  named_property_binding_vector npbv(LEDrep);
327
328  cout << npbv << '\n'; 
329 */
330 }
331
332 int main()
333 {
334  using namespace OC::OCReflect;
335
336  convert_test(); 
337
338  call_test();
339
340  rep_test();
341
342  from_rep_test();
343 }