File: test087.cxx

package info (click to toggle)
libpqxx 4.0.1%2Bdfsg3-8
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 16,012 kB
  • ctags: 9,469
  • sloc: sh: 11,289; cpp: 10,801; xml: 1,256; makefile: 287; ansic: 195; python: 159
file content (141 lines) | stat: -rw-r--r-- 3,117 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <cctype>
#include <cerrno>
#include <cstring>
#include <ctime>
#include <iostream>

#if defined(PQXX_HAVE_SYS_SELECT_H)
#include <sys/select.h>
#else
#include <sys/types.h>
#if defined(PQXX_HAVE_UNISTD_H)
#include <unistd.h>
#endif
#if defined(_WIN32)
#define NOMINMAX
#include <winsock2.h>
#endif
#endif // PQXX_HAVE_SYS_SELECT_H

#include "test_helpers.hxx"

using namespace PGSTD;
using namespace pqxx;


// Test program for libpqxx.  Send notification to self, and select() on socket
// as returned by the connection to wait for it to come in.  Normally one would
// use connection_base::await_notification() for this, but the socket may be
// needed for event loops waiting on multiple sources of events.
namespace
{
// Sample implementation of notification receiver.
class TestListener : public notification_receiver
{
  bool m_done;

public:
  explicit TestListener(connection_base &C, string Name) :
    notification_receiver(C, Name), m_done(false)
  {
  }

  virtual void operator()(const string &, int be_pid)
  {
    m_done = true;
    PQXX_CHECK_EQUAL(
	be_pid,
	conn().backendpid(),
	"Notification came from wrong backend process.");

    cout << "Received notification: " << channel() << " pid=" << be_pid << endl;
  }

  bool done() const { return m_done; }
};


// A transactor to trigger our notification listener
class Notify : public transactor<nontransaction>
{
  string m_channel;

public:
  explicit Notify(string NotifName) :
    transactor<nontransaction>("Notifier"), m_channel(NotifName) { }

  void operator()(argument_type &T)
  {
    T.exec("NOTIFY \"" + m_channel + "\"");
  }

  void on_abort(const char Reason[]) throw ()
  {
    try
    {
      cerr << "Notify failed!" << endl;
      if (Reason) cerr << "Reason: " << Reason << endl;
    }
    catch (const exception &)
    {
    }
  }
};


extern "C"
{
static void set_fdbit(fd_set &s, int b)
{
#ifdef _MSC_VER 
// Suppress pointless, unfixable warnings in Visual Studio.
#pragma warning ( push ) 
#pragma warning ( disable: 4389 ) // Signed/unsigned mismatch.
#pragma warning ( disable: 4127 ) // Conditional expression is constant.
#endif 

  // Do the actual work.
  FD_SET(b,&s);

#ifdef _MSV_VER
// Restore prevalent warning settings.
#pragma warning ( pop )
#endif
}
}


void test_087(transaction_base &orgT)
{
  connection_base &C(orgT.conn());
  orgT.abort();

  const string NotifName = "my notification";
  cout << "Adding listener..." << endl;
  TestListener L(C, NotifName);

  cout << "Sending notification..." << endl;
  C.perform(Notify(L.channel()));

  int notifs = 0;
  for (int i=0; (i < 20) && !L.done(); ++i)
  {
    PQXX_CHECK_EQUAL(notifs, 0, "Got unexpected notifications.");

    cout << ".";
    const int fd = C.sock();
    fd_set fds;
    FD_ZERO(&fds);
    set_fdbit(fds,fd);
    timeval timeout = { 1, 0 };
    select(fd+1, &fds, 0, &fds, &timeout);
    notifs = C.get_notifs();
  }
  cout << endl;

  PQXX_CHECK(L.done(), "No notification received.");
  PQXX_CHECK_EQUAL(notifs, 1, "Got unexpected number of notifications.");
}
} // namespace

PQXX_REGISTER_TEST_T(test_087, nontransaction)