File: sockets2.cpp

package info (click to toggle)
mldemos 0.5.1-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 32,224 kB
  • ctags: 46,525
  • sloc: cpp: 306,887; ansic: 167,718; ml: 126; sh: 109; makefile: 2
file content (202 lines) | stat: -rw-r--r-- 6,438 bytes parent folder | download | duplicates (4)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// Copyright (C) 2008  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.

#include "tester.h"
#include <dlib/sockets.h>
#include <dlib/threads.h>
#include <dlib/array.h>
#include <algorithm>

// This is called an unnamed-namespace and it has the effect of making everything 
// inside this file "private" so that everything you declare will have static linkage.  
// Thus we won't have any multiply defined symbol errors coming out of the linker when 
// we try to compile the test suite.
namespace  
{
    using namespace test;
    using namespace dlib;
    using namespace std;
    // Declare the logger we will use in this test.  The name of the logger 
    // should start with "test."
    dlib::logger dlog("test.sockets2");


    class sockets2_tester : public tester, private multithreaded_object 
    {
        /*!
            WHAT THIS OBJECT REPRESENTS
                This object represents a unit test.  When it is constructed
                it adds itself into the testing framework.
        !*/

        short port_num;
        string data_to_send;

        bool test_failed;

        void write_thread (
        )
        {
            try
            {
                scoped_ptr<connection> con(connect("127.0.0.1", port_num));

                // Send a copy of the data down the connection so we can test our the read() function
                // that uses timeouts in the main thread.
                if (con->write(data_to_send.data(), data_to_send.size()) != (int)data_to_send.size())
                {
                    test_failed = true;
                    dlog << LERROR << "failed to send all the data down the connection";
                }

                close_gracefully(con,300000);
            }
            catch (exception& e)
            {
                test_failed = true;
                dlog << LERROR << e.what();
            }
        }

        void no_write_thread (
        )
        {
            try
            {
                scoped_ptr<connection> con(connect("127.0.0.1", port_num));

                // just do nothing until the connection closes
                char ch;
                con->read(&ch, 1);
                dlog << LDEBUG << "silent connection finally closing";
            }
            catch (exception& e)
            {
                test_failed = true;
                dlog << LERROR << e.what();
            }
        }

    public:
        sockets2_tester (
        ) :
            tester (
                "test_sockets2",       // the command line argument name for this test
                "Run sockets2 tests.", // the command line argument description
                0                     // the number of command line arguments for this test
            )
        {
            register_thread(*this, &sockets2_tester::write_thread);
            register_thread(*this, &sockets2_tester::write_thread);
            register_thread(*this, &sockets2_tester::write_thread);
            register_thread(*this, &sockets2_tester::write_thread);
            register_thread(*this, &sockets2_tester::write_thread);
            register_thread(*this, &sockets2_tester::no_write_thread);
        }

        void perform_test (
        )
        {
            run_tests(0);
            run_tests(40);
        }

        void run_tests (
            unsigned long timeout_to_use
        )
        {
            // make sure there aren't any threads running
            wait();

            port_num = 5000;
            test_failed = false;

            print_spinner();
            data_to_send = "oi 2m3ormao2m fo2im3fo23mi o2mi3 foa2m3fao23ifm2o3fmia23oima23iom3giugbiua";
            // make the block of data much larger
            for (int i = 0; i < 11; ++i)
                data_to_send = data_to_send + data_to_send;

            dlog << LINFO << "data block size: " << data_to_send.size();


            scoped_ptr<listener> list;
            DLIB_TEST(create_listener(list, port_num, "127.0.0.1") == 0);
            DLIB_TEST(list);

            // kick off the sending threads
            start();


            array<scoped_ptr<connection> > cons;
            std::vector<long> bytes_received(6,0);
            scoped_ptr<connection> con_temp;
            
            // accept the 6 connections we should get
            for (int i = 0; i < 6; ++i)
            {
                DLIB_TEST(list->accept(con_temp) == 0);
                cons.push_back(con_temp);
                print_spinner();
            }

            int finished_cons = 0;

            // now receive all the bytes from the sending threads
            while (finished_cons < 5)
            {
                for (unsigned long i = 0; i < cons.size(); ++i)
                {
                    if (cons[i])
                    {
                        const int buf_size = 3000;
                        char buf[buf_size];

                        int status = cons[i]->read(buf, buf_size, timeout_to_use);

                        if (status > 0)
                        {
                            DLIB_TEST(equal(buf, buf+status, data_to_send.begin()+bytes_received[i]));
                            bytes_received[i] += status;
                        }
                        else if (status == 0)
                        {
                            // the connection is closed to kill it
                            cons[i].reset();
                            ++finished_cons;
                        }
                    }
                }
                print_spinner();
            }

            for (unsigned long i = 0; i < bytes_received.size(); ++i)
            {
                DLIB_TEST(bytes_received[i] == (long)data_to_send.size() || cons[i]);
            }


            dlog << LINFO << "All data received correctly";

            cons.clear();


            print_spinner();

            DLIB_TEST(test_failed == false);


            // wait for all the sending threads to terminate
            wait();
        }
    };

    // Create an instance of this object.  Doing this causes this test
    // to be automatically inserted into the testing framework whenever this cpp file
    // is linked into the project.  Note that since we are inside an unnamed-namespace 
    // we won't get any linker errors about the symbol a being defined multiple times. 
    sockets2_tester a;

}