iutest  1.17.99.14
iutest_sstp_notifier.hpp
[詳解]
1 //======================================================================
2 //-----------------------------------------------------------------------
13 //-----------------------------------------------------------------------
14 //======================================================================
15 #ifndef INCG_IRIS_IUTEST_SSTP_NOTIFIER_HPP_1187A63F_E99B_4289_A562_3C87B9739B7D_
16 #define INCG_IRIS_IUTEST_SSTP_NOTIFIER_HPP_1187A63F_E99B_4289_A562_3C87B9739B7D_
17 
18 //======================================================================
19 // include
20 #include "../iutest_core.hpp"
21 
22 #if IUTEST_HAS_STREAM_RESULT
23 #include "../internal/iutest_socket.hpp"
24 
25 #ifndef IUTEST_SSTPNOTIFIER_JAPANESE
26 # define IUTEST_SSTPNOTIFIER_JAPANESE 1
27 #endif
28 
29 namespace iutest
30 {
31 
32 //======================================================================
33 // class
34 namespace detail
35 {
36 
40 class SSTP : public Socket
41 {
42 public:
43  enum eCharset
44  {
45  CHARSET_ASCII
46  , CHARSET_SHIFTJIS
47  , CHARSET_ISO_220_JP
48  , CHARSET_EUC_JP
49  , CHARSET_UTF8
50  };
51  enum eOption
52  {
53  OPTION_NODESCRIPT = 0x0001
54  , OPTION_NOTRANSLATE= 0x0002
55  };
56  static const int DEFAULT_PORT=9801;
57 
58 private:
59  class Response
60  {
61  public:
62  ::std::string m_message;
63  int m_major;
64  int m_minor;
65  int m_code;
66  public:
67  template<size_t N>
68  explicit Response(const char (&str)[N])
69  : m_major(0), m_minor(0), m_code(0)
70  {
71  Parse(str);
72  }
73  public:
74  template<size_t N>
75  bool Parse(const char (&str)[N])
76  {
77  m_code = -1;
78  if( !detail::IsStringForwardMatching(str, "SSTP/") ) {
79  return false;
80  }
81  char* p=NULL;
82  m_major = strtol(str+5, &p, 10);
83  m_minor = strtol(p+1, &p, 10);
84  m_code = strtol(p+1, &p, 10);
85  m_message = p;
86  return true;
87  }
88  };
89 public:
90  explicit SSTP(const ::std::string& sender, eCharset charset=CHARSET_SHIFTJIS)
91  : m_Sender(sender), m_Charset(charset), m_bInitialOpen(false) {}
92 
93 public:
94  bool Open(const char* host, const char* port)
95  {
96  m_Host = host;
97  m_Port = port;
98  m_bInitialOpen = Socket::Open(host, port);
99  return m_bInitialOpen;
100  }
101 public:
102  SSTP& Notify()
103  {
104  if( m_bInitialOpen && Socket::Open(m_Host.c_str(), m_Port.c_str()) )
105  {
106  SendLn("NOTIFY SSTP/1.1");
107  SendLn("Sender: " + m_Sender);
108  SendLn("Charset: " + FormatCharset(m_Charset));
109  }
110  return *this;
111  }
112  SSTP& End()
113  {
114  SendLn("");
115  Recv();
116  Close();
117  return *this;
118  }
119 public:
120  SSTP& Event(const ::std::string& id)
121  {
122  SendLn("Event: " + id);
123  return *this;
124  }
125  SSTP& Reference(int index, const ::std::string& info)
126  {
127  SendLn("Reference" + StreamableToString(index) + ": " + info);
128  return *this;
129  }
130  SSTP& Script(const ::std::string& script)
131  {
132  SendLn("Script: " + MultiByteStringToUTF8(script.c_str()));
133  return *this;
134  }
135  SSTP& Option(eOption option)
136  {
137  SendLn("Option: " + FormatOption(option));
138  return *this;
139  }
140  SSTP& Locale(const ::std::string& locale)
141  {
142  SendLn("Locale: " + locale);
143  return *this;
144  }
145  SSTP& Marker(const ::std::string& maker)
146  {
147  SendLn("Marker: " + maker);
148  return *this;
149  }
150  SSTP& Entry(const ::std::string& entry)
151  {
152  SendLn("Entry: " + entry);
153  return *this;
154  }
155  SSTP& Hwnd(UInt32 hWnd)
156  {
157  SendLn("HWnd: " + StreamableToString(hWnd));
158  return *this;
159  }
160  SSTP& IfGhost(const ::std::string& ghost)
161  {
162  SendLn("IfGhost: " + ghost);
163  return *this;
164  }
165 private:
166  void Recv()
167  {
168  char buf[1024];
169  if( Read(buf, sizeof(buf)) )
170  {
171 #if defined(_IUTEST_DEBUG)
172  puts(buf);
173 #endif
174  Response res(buf);
175  if( res.m_code < 200 || res.m_code >= 300 )
176  {
177  IUTEST_LOG_(WARNING) << buf;
178  }
179  }
180  }
181 private:
182  ::std::string FormatCharset(eCharset charset)
183  {
184  switch (charset)
185  {
186  case CHARSET_ASCII:
187  default:
188  return "ASCII";
189  case CHARSET_SHIFTJIS:
190  return "Shift_JIS";
191  case CHARSET_ISO_220_JP:
192  return "ISO-2022-JP";
193  case CHARSET_EUC_JP:
194  return "EUC-JP";
195  case CHARSET_UTF8:
196  return "UTF-8";
197  }
198  }
199  ::std::string FormatOption(eOption option)
200  {
201  ::std::string str="";
202  if( option & OPTION_NODESCRIPT )
203  {
204  str += "nodescript";
205  }
206  if( option & OPTION_NOTRANSLATE )
207  {
208  if( !str.empty() )
209  {
210  str += ",";
211  }
212  str += "notranslate";
213  }
214  return "";
215  }
216 private:
217  ::std::string m_Sender;
218  ::std::string m_Host;
219  ::std::string m_Port;
220  eCharset m_Charset;
221  bool m_bInitialOpen;
222 };
223 
224 } // end of namespace detail
225 
226 namespace ukagaka
227 {
228 
232 class SakuraScript
233 {
234 public:
235  SakuraScript() {}
236  explicit SakuraScript(const char* script) : m_script(script) {}
237  explicit SakuraScript(const ::std::string& script) : m_script(script) {}
238 public:
239  SakuraScript& Append(const ::std::string& str)
240  {
241  m_script.append(str);
242  return *this;
243  }
244  template<typename T>
245  SakuraScript& Append(const T& v)
246  {
247  m_script.append(StreamableToString(v));
248  return *this;
249  }
250 
251 public:
252  SakuraScript& Surface(int id) { Append("\\s[" + StreamableToString(id) + "]"); return *this; }
253  SakuraScript& Animate(int id) { Append("\\i[" + StreamableToString(id) + "]"); return *this; }
254  SakuraScript& Concat() { m_script.insert(0, "\\C"); return *this; }
255  SakuraScript& Ln() { Append("\\n"); return *this; }
256  SakuraScript& Home() { Append("\\h"); return *this; }
257  SakuraScript& You() { Append("\\u"); return *this; }
258  SakuraScript& Scope(int id) { Append("\\p[" + StreamableToString(id) + "]"); return *this; }
259  SakuraScript& Quick() { Append("\\_q"); return *this; }
260 
261  SakuraScript& Open(const ::std::string& file) { Append("\\![open,file," + file + "]"); return *this; }
262 
263 public:
264  const ::std::string& ToString()
265  {
266  // 改行は改行タグに変更する
267  detail::StringReplace(m_script, '\n', "\\n");
268  return m_script;
269  }
270 
271 public:
272  SakuraScript& operator + (const ::std::string& str)
273  {
274  return Append(str);
275  }
276  template<typename T>
277  SakuraScript& operator + (const T& v)
278  {
279  return Append(v);
280  }
281 
282 private:
283  ::std::string m_script;
284 };
285 
286 namespace ghost
287 {
288 
292 struct Emily4
293 {
294  enum
295  {
296  Normal = 0
297  , Shy
298  , Surprise
299  , Anxiety
300  , Shocke
301  , Smile
302  , EyesClose
303  , Angry
304  , BitterSmile
305  , AngerToCoverEmbarrassment
306  , Fidget = 21
307  //, Exhilarated = 25 //!< わはー
308  , Question
309  , Derision
310  , ShyEyesClose = 31
311  , Blubber = 34
312  , Explosion = 40
313  , Thoughtful = 127
314  };
315 
316  struct Skill
317  {
318  enum
319  {
320  TypeA = 24
321  , TypeB = 124
322  , TypeC = 1024
323  , TypeD = 1124
324  };
325  };
326 
327  struct Doll
328  {
329  enum
330  {
331  Todo = 20
332  };
333  };
334 
335  struct Coock
336  {
337  enum
338  {
339  Shy = 51
340  , Anxiety = 53
341  , Smile = 55
342  , EyesClose
343  };
344  };
345 };
346 
347 } // end of namespace ghost
348 } // end of namespace ukagaka
349 
353 class SSTPNotifier : public EmptyTestEventListener
354 {
355  typedef ukagaka::SakuraScript Script;
356  typedef ukagaka::ghost::Emily4 Ghost;
357 public:
358  explicit SSTPNotifier(const char* host, int port=detail::SSTP::DEFAULT_PORT);
359 
360 public:
361  virtual void OnTestProgramStart(const UnitTest& test) IUTEST_CXX_OVERRIDE;
362  virtual void OnTestIterationStart(const UnitTest& test
363  , int iteration) IUTEST_CXX_OVERRIDE;
364  virtual void OnTestSuiteStart(const TestSuite& test_suite) IUTEST_CXX_OVERRIDE;
365  virtual void OnTestStart(const TestInfo& test_info) IUTEST_CXX_OVERRIDE;
366  virtual void OnTestPartResult(const TestPartResult& test_part_result) IUTEST_CXX_OVERRIDE;
367  virtual void OnTestRecordProperty(const TestProperty& test_property) IUTEST_CXX_OVERRIDE;
368  virtual void OnTestEnd(const TestInfo& test_info) IUTEST_CXX_OVERRIDE;
369  virtual void OnTestSuiteEnd(const TestSuite& test_suite) IUTEST_CXX_OVERRIDE;
370  virtual void OnTestIterationEnd(const UnitTest& test
371  , int iteration) IUTEST_CXX_OVERRIDE;
372  virtual void OnTestProgramEnd(const UnitTest& test) IUTEST_CXX_OVERRIDE;
373 
374 private:
375  ::std::string FormatMessage(const ::std::string& path);
376  ::std::string FormatPath(const ::std::string& path);
377  ::std::string FormatBool(bool b);
378 private:
379  detail::SSTP m_sstp;
380 
382 
383 public:
387  static TestEventListener* SetUp(const char* host, int port=detail::SSTP::DEFAULT_PORT)
388  {
389  TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
390  TestEventListener* p = new SSTPNotifier(host, port);
391  listeners.Append(p);
392  return p;
393  }
394 };
395 
396 } // end of namespace iutest
397 
398 namespace iutest
399 {
400 
401 IUTEST_IPP_INLINE SSTPNotifier::SSTPNotifier(const char* host, int port)
402  : m_sstp("iutest", detail::SSTP::CHARSET_UTF8)
403 {
404  if( !m_sstp.Open(host, StreamableToString(port).c_str()) )
405  {
406  IUTEST_LOG_(WARNING) << "SSTPNotifier: failed connect to " << host << ":" << port;
407  }
408 }
409 
410 
411 IUTEST_IPP_INLINE void SSTPNotifier::OnTestProgramStart(const UnitTest& test)
412 {
413  IUTEST_UNUSED_VAR(test);
414  m_sstp.Notify()
415 #if IUTEST_SSTPNOTIFIER_JAPANESE
416  .Script(Script("テストスタ~ト").Ln().ToString())
417 #else
418  .Script(Script("Start test.").Ln().ToString())
419 #endif
420  .End();
421 }
422 IUTEST_IPP_INLINE void SSTPNotifier::OnTestIterationStart(const UnitTest& test
423  , int iteration)
424 {
425  IUTEST_UNUSED_VAR(test);
426  m_sstp.Notify()
427 #if IUTEST_SSTPNOTIFIER_JAPANESE
428  .Script(Script(StreamableToString(iteration + 1) + "回目のテストだよ").Concat().Ln().ToString())
429 #else
430  .Script(Script(StreamableToString(iteration+1) + "-th test.").Concat().Ln().ToString())
431 #endif
432  .End();
433 }
434 IUTEST_IPP_INLINE void SSTPNotifier::OnTestSuiteStart(const TestSuite& test_suite)
435 {
436  m_sstp.Notify()
437  .Script(Script().Surface(Ghost::Normal)
438 #if IUTEST_SSTPNOTIFIER_JAPANESE
439  .Append(StreamableToString(test_suite.name()) + " TestSuite を開始").Concat().Ln().ToString())
440 #else
441  .Append(StreamableToString(test_suite.name()) + " Start TestSuite...").Concat().Ln().ToString())
442 #endif
443  .End();
444 }
445 IUTEST_IPP_INLINE void SSTPNotifier::OnTestStart(const TestInfo& test_info)
446 {
447  m_sstp.Notify()
448  .Script(Script().Surface(Ghost::Normal)
449 #if IUTEST_SSTPNOTIFIER_JAPANESE
450  .Append(StreamableToString(test_info.name()) + " テストを開始").Concat().Ln().ToString())
451 #else
452  .Append(StreamableToString(test_info.name()) + " Start Test...").Concat().Ln().ToString())
453 #endif
454  .End();
455 }
456 IUTEST_IPP_INLINE void SSTPNotifier::OnTestPartResult(const TestPartResult& test_part_result)
457 {
458  const char* filename = test_part_result.file_name();
459  if( filename == NULL )
460  {
461  filename = "";
462  }
463 
464  if( test_part_result.passed() )
465  {
466  }
467  else
468  {
469  m_sstp.Notify()
470  .Script(Script().Surface(Ghost::Anxiety).Append(FormatPath(filename)
471 #if IUTEST_SSTPNOTIFIER_JAPANESE
472  + "の" + StreamableToString(test_part_result.line_number()) + "行目で失敗したよ\n"
473 #else
474  + ": " + StreamableToString(test_part_result.line_number()) + ": Failed\n"
475 #endif
476  + FormatMessage(test_part_result.message())).Concat().Ln().Open(FormatPath(filename)).ToString())
477  .End();
478  }
479 }
480 IUTEST_IPP_INLINE void SSTPNotifier::OnTestRecordProperty(const TestProperty& test_property)
481 {
482  m_sstp.Notify()
483  .Script(Script("TestRecordProperty:" + StreamableToString(test_property.key())
484  + "=" + test_property.value()).Concat().Ln().ToString())
485  .End();
486 }
487 IUTEST_IPP_INLINE void SSTPNotifier::OnTestEnd(const TestInfo& test_info)
488 {
489  m_sstp.Notify()
490  .Script(Script().Surface(test_info.Passed() ? Ghost::Smile : Ghost::Angry)
491  .Append( FormatBool(test_info.Passed())
492 #if IUTEST_SSTPNOTIFIER_JAPANESE
493  + "したよ"
494 #endif
495  + "(" + StreamableToString(test_info.elapsed_time()) + "ms)").Concat().Ln().ToString())
496  .End();
497 }
498 IUTEST_IPP_INLINE void SSTPNotifier::OnTestSuiteEnd(const TestSuite& test_suite)
499 {
500  m_sstp.Notify()
501  .Script(Script(StreamableToString(test_suite.name())
502 #if IUTEST_SSTPNOTIFIER_JAPANESE
503  + " TestSuite は" + FormatBool(test_suite.Passed()) + "したよ"
504 #else
505  + " TestSuite is" + FormatBool(test_suite.Passed()) + "."
506 #endif
507  + "(" + StreamableToString(test_suite.elapsed_time()) + "ms)").Concat().Ln().ToString())
508  .End();
509 }
510 IUTEST_IPP_INLINE void SSTPNotifier::OnTestIterationEnd(const UnitTest& test
511  , int iteration)
512 {
513  IUTEST_UNUSED_VAR(test);
514  IUTEST_UNUSED_VAR(iteration);
515 }
516 IUTEST_IPP_INLINE void SSTPNotifier::OnTestProgramEnd(const UnitTest& test)
517 {
518  IUTEST_UNUSED_VAR(test);
519  m_sstp.Notify()
520 #if IUTEST_SSTPNOTIFIER_JAPANESE
521  .Script(Script("おわり").Concat().Ln().ToString())
522 #else
523  .Script(Script("Finish!").Concat().Ln().ToString())
524 #endif
525  .End();
526  m_sstp.Close();
527 }
528 
529 IUTEST_IPP_INLINE ::std::string SSTPNotifier::FormatMessage(const ::std::string& path)
530 {
531  ::std::string str = path;
532  detail::StringReplace(str, '\\', "/");
533  return str;
534 }
535 
536 IUTEST_IPP_INLINE ::std::string SSTPNotifier::FormatPath(const ::std::string& path)
537 {
538  ::std::string str = path;
539  detail::StringReplace(str, '\\', "/");
540  return str;
541 }
542 
543 IUTEST_IPP_INLINE ::std::string SSTPNotifier::FormatBool(bool b)
544 {
545 #if IUTEST_SSTPNOTIFIER_JAPANESE
546  return b ? "成功" : "失敗";
547 #else
548  return b ? "Succeeded" : "Failed";
549 #endif
550 }
551 
552 } // end of namespace iutest
553 
554 #endif
555 
556 #endif // INCG_IRIS_IUTEST_SSTP_NOTIFIER_HPP_1187A63F_E99B_4289_A562_3C87B9739B7D_
static UnitTest * GetInstance()
UnitTest インスタンスの取得
Definition: iutest_core.hpp:43
TestEventListeners & listeners() const
Definition: iutest_core.hpp:123
detail::iuConcatParamHolder< Generator1, Generator2 > Concat(const Generator1 &g1, const Generator2 &g2)
値配列パラメータ
Definition: iutest_param_tests.hpp:578
#define IUTEST_CXX_OVERRIDE
override definition
Definition: iutest_compiler.hpp:747
#define IUTEST_LOG_(level)
ログメッセージストリーム
Definition: iutest_port.hpp:56
#define IUTEST_PP_DISALLOW_COPY_AND_ASSIGN(TypeName)
コピー禁止定義
Definition: iutest_pp.hpp:31
iutest root namespace
Definition: iutest_charcode.hpp:33
detail::type_fit_t< 4 >::UInt UInt32
32 bit 符号なし整数型
Definition: iutest_defs.hpp:503