Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | Related Pages | Examples

testing.html

00001 /**
00002 
00003 @page Testing Testing
00004 The following pages contain tests for our framework.
00005 
00006 - @subpage TestConnect
00007 - @subpage TestConnectComplex
00008 - @subpage TestConnectMultiple
00009 - @subpage TestConstruct
00010 - @subpage TestUpdate
00011 - @subpage TestAction
00012 - @subpage TestDestruct
00013 - @subpage TestPlugin
00014 - @subpage TestPluginChain
00015 - @subpage TestPointer
00016 - @subpage TestPointerUnres
00017 - @subpage TestPointerUnset
00018 - @subpage TestPointerChange
00019 - @subpage TestReadObj
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 @page TestConnect 1. Connection (simple)
00028 The following test will just test connection from a client to a server.
00029 
00030 @section ClientApplication Client Application
00031 The following code shows a very simple client, the client just initiates its connection to a given host on port 8000 and displays when ClientFramework::onConnect() is called.
00032 @include testing/1_connection/client_main.cpp
00033 
00034 @section ServerApplication Server Application
00035 The following is the server for this test, it is also very simple. It just listenes on port 8000 and then print when clients connect and disconnect.
00036 @include testing/1_connection/server_main.cpp
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 @page TestConnectComplex 2. Connection (complex: use handshaking)
00045 This test will send along data during the handshaking/connection phase, to validate the client. The following things will be tested:
00046 - %Client sends a username using ClientFramework::writeHandshakeInitMessage(FrameworkPacket * fp)
00047    - Server accepts it
00048    - Server rejects it
00049 - Server sends a version number using ServerFramework::onInitialHandshake(FrameworkPacket * handshake, FrameworkPacket * reply)
00050    - %Client accepts it
00051    - %Client rejects it
00052 
00053 @section ClientApplication Client Application
00054 The following code shows a very simple client, the client just initiates its connection to a given host and sends a username along. If it receives a discontinue packet it prints out a reason sent by the server. If it receives a continue-packet it checks a version string sent by the server with its own version string and either sends a continue-packet or a discontinue packet.
00055 @include testing/2_handshaking/client_main.cpp
00056 
00057 @section ServerApplication Server Application
00058 The following is the server for this test, it is rather simple. It checks the username sent by the server, anf if it matches it sends a continue packet with its version string. If it does not match it sends a discontinue-packet.
00059 @include testing/2_handshaking/server_main.cpp
00060 
00061 
00062 
00063 
00064 
00065 @page TestConnectMultiple 3. Multiple clients connecting
00066 This test will have multiple clients connecting and handshaking at the same time, the source for this test is the same as for test @ref TestConnectComplex, we just start multiple clients to see that everything works as expected.
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 @page TestConstruct 4. Construction of objects
00077 This test will set up a ServerData object on the server and then call ServerData::sendCreateObjectToAll(). The client will have set up a static method for creating objects of this class using the method:
00078 \code
00079 ClientFramework::registerConstructor(unsigned int class_id, ClientData * (*func)(ClientFramework *, FrameworkPacket *))
00080 \endcode
00081 This method should be called, and a new ClientData object should be created from the FrameworkPacket.
00082 
00083 @section ClientApplication Client Application
00084 In this example you should notice the new class MyClientData, which is a subclass of ClientData. This class has a static method that constructs new objects of this class. It is not necessary to place this static method on the class it self, but it makes sense to keep them together.
00085 
00086 You should also notice how this "constructor" method is registered in the ClientFramework, the most important thing is the ID with which it is registered, this ID is the same as the server-object uses to specify what "constructor" function to use. Hence they MUST match.
00087 
00088 Also you should notice the constructor of MyClientData, it takes the framework and the packet with which it should be constructed as arguments. And after calling its superclasses constructor it reads the values from the supplied ClientPacket.
00089 
00090 @include testing/4_constructors/client_main.cpp
00091 
00092 @section ServerApplication Server Application
00093 This test-server has like the test-client a datatype MyServerData, and this class is a subclass of ServerData.
00094 
00095 The interesting things to notice in this test are the method fillCreateObjectPacket() and getClassId() which are called when the ServerFramework wants to create a constructor packet. The getClassId() MUST match the ID with which the constructor function is registered on the client, and the fillCreateObjectPacket() must fill in all data required for the client-version of this data-type to construct.
00096 
00097 The object-ID (as opposed to the Class-ID) of the data (which is the same on the server and client version of the data-entity, you need not worry about, this will be taken care of by the framework).
00098 @include testing/4_constructors/server_main.cpp
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 @page TestUpdate 5. Update of objects
00113 In this test we will set up a ServerData object on the server, replicate it to the client upon connect using the member-method:
00114 \code
00115 void sendCreateObject( Client * client) const;
00116 \endcode
00117 Then during each pass of the mainLoop on the server, we will change the object and send an update to all connected clients using the member-method:
00118 \code
00119 void sendUpdateToAll(unsigned char type, bool reliable) const;
00120 \endcode
00121 The client will print out the object during each pass of its mainLoop, thus showing the change.
00122 
00123 @section ClientApplication Client Application
00124 In this example you should notice the implementation of the member method:
00125 \code
00126 virtual void updatePacket(ClientFramework * f, char updatetype, ClientPacket * packet);
00127 \endcode
00128 This is the method which is called when we receive updates from the server. The updatetype is used to determine which kind of update this is. In this simple test we only use one type, but you can specify any number from 4 to 255. The update-types below 4 are reserved for constructors, destructors, plugins and the framework packets.
00129 
00130 @include testing/5_object_updates/client_main.cpp
00131 
00132 @section ServerApplication Server Application
00133 There is not much to notice here, we create 3 dataobjects and each pass in the mainLoop we update their position, and send an update to all connected clients. You should notice the member method:
00134 \code
00135 virtual void fillUpdatePacket(ServerPacket * packet, unsigned char type) const;
00136 \endcode
00137 This method is called when ever we need an update packet of a specific type from the object. All this method does in this example is write its coordinates to the packet.
00138 
00139 @include testing/5_object_updates/server_main.cpp
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 @page TestAction 6. Actions sent from Client-object to Server-object
00154 This test will set up a ServerData object on the server, replicate it to the client, and then the client will call the ClientData::updatePacket(ClientFramework * f, char updatetype, FrameworkPacket * packet) method to send an action back the server-version of the object.
00155 
00156 @section ClientApplication Client Application
00157 In this example you should notice the implementation of the member method:
00158 \code
00159 MyClientData::sendSomeAction();
00160 \endcode
00161 This is the method that sends an action to the server. The parameters for constructing a packet are described in the source.
00162 
00163 @include testing/6_object_actions/client_main.cpp
00164 
00165 @section ServerApplication Server Application
00166 This test-server does not do much, it just prints out the actions when they are received. The actions are received in the virtual method:
00167 \code
00168 virtual void clientPacket(Client * client, unsigned char type, ServerPacket * packet);
00169 \endcode
00170 
00171 @include testing/6_object_actions/server_main.cpp
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 @page TestDestruct 7. Destruction of objects
00186 This test will set up a ServerData object on the server, replicate it to the client and then destroy it on the server. This should result in a call to ServerData::sendDestroyToAll() and the client should destroy the object as well.
00187 
00188 @section ClientApplication Client Application
00189 There is not much to notice in this client-application. All it does it print out when ever an object is constructed and when ever it is destructed. Every pass in the mainLoop it prints out how many objects are registered in the framework, to make sure that they are also unregistered upon destruction.
00190 
00191 @include testing/7_destructors/client_main.cpp
00192 
00193 @section ServerApplication Server Application
00194 The server just creates new objects every 5th pass in the mainLoop, and destroys them all again every 27th pass. Before it destroys them, it calls the method:
00195 \code
00196 virtual void sendDestroyObjectToAll();
00197 \endcode
00198 To make sure all connected clients receive word of the object no longer being on the server. You should note however that you can instruct a client to destroy an object even though this object remains on the server, this could be the case if the object for some reason is no longer visible to a specific client.
00199 
00200 @include testing/7_destructors/server_main.cpp
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 @page TestPlugin 8. Plugins (pack/unpack)
00215 In this test we create a plugin that aggregates packets and send one collected packet when purged. This is a good example of the usage of plugins, since it makes sense to sometimes want to aggregate all data to a client into bulks, to minimize overhead.
00216 
00217 @section MyTestPlugin Test Plugin
00218 The plugin has both a packing and unpacking side to it. The packing side gets packets in the member method:
00219 \code
00220 Plugin::pack(PacketType * packet);
00221 \endcode
00222 Here it appends the packet to a packet for the given client. If no packet for this client exists it creates one. When the server calls the "purge()" method the plugin wraps up it's packets and sends them along.
00223 
00224 On the receiving side the plugin will read the size of the packets, one by one, untill it reads a 0 size packet, this means that there are no more packets, and the readin stops. All this happens in the unpack(...) method.
00225 
00226 @include testing/8_plugins/test_plugin.h
00227 
00228 @section ClientApplication Client Application
00229 The client application in this example uses the member method:
00230 \code
00231 ClientFramework::registerPlugin(Plugin<ClientPacket> * plugin);
00232 \endcode
00233 to register the plugin. It should be noted that opposed to the server the client does not specify chains of plugins, since every unpacking should result in new packets forwarded back to the inqueue. That way recursively unpacking nested packets.
00234 
00235 @include testing/8_plugins/client_main.cpp
00236 
00237 @section ServerApplication Server Application
00238 The server in this test creates some objects first. Then when a client connects, it switches the presending chain to use the plugin we have created for the test. Then it sends the client constructor packets for all the data. Finally it purges the presending chain, to let the plugin know that it should send along its aggregated packets. After this it changes back to the default presending chain (the chain where packets are inserted directly into the outqueue).
00239 
00240 @include testing/8_plugins/server_main.cpp
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 @page TestPluginChain 9. Presending chains (multiple pack/unpack)
00255 In this test we will create a chain of plugins on the server, and on the client the nested wrapping should be unpacked correctly.
00256 
00257 @section AggrPlugin Aggregation Plugin
00258 The first plugin is the same as in the previous excample, it aggregates packets into one large packet.
00259 
00260 @include testing/9_presending_chains/aggr_plugin.h
00261 
00262 @section ZlibPlugin ZLIB compression Plugin
00263 The second plugin is a compression plugin using <a href="http://www.zlib.net/">Zlib</a>. This plugin does not need the onPurge(...) method, because it just forwards the compressed data-packet. The combination of these two plugins is smart, since packets are first collected into one large packet and then compressed to minimize bandwidth usage.
00264 
00265 @include testing/9_presending_chains/zlib_plugin.h
00266 
00267 
00268 @section ClientApplication Client Application
00269 The client application is the same as the example before, except this one registeres both plugins.
00270 
00271 @include testing/9_presending_chains/client_main.cpp
00272 
00273 @section ServerApplication Server Application
00274 The server in this test is almost the same as in the previous test, except the presending chain in this application contains two plugins. We also create a little more objects to better see the impact of the compression.
00275 
00276 @include testing/9_presending_chains/server_main.cpp
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 @page TestPointer 10. Pointer (simple: write - read)
00289 This test will create two ServerData objects on the server, one with a pointer to the other. This is a very small <a href="http://en.wikipedia.org/wiki/Tree_%28graph_theory%29">tree</a>, and the objects are sent to the client bottom up. The client should then be able to look up the object that is pointed to (the pointee) and correctly assign the pointer on the pointing object.
00290 
00291 @section ClientApplication Client Application
00292 The client application here just prints out the dataobjects when they are constructed. That way we can see what they are pointing at. You should notice the method called on the packet:
00293 \code
00294 template<class T>
00295 void ClientPacket::readPtr( ClientData * receiver, T ** ptrptr, ClientFramework * framework );
00296 \endcode
00297 This method will be given the object trying to read the pointer, and a pointer-pointer to the pointer its trying to read. The framework is also supplied because the object is being lookup here. If the object cannot be found the pointer will be set to NULL (this is possible because we get a pointer-pointer).
00298 
00299 @include testing/10_pointers/client_main.cpp
00300 
00301 @section ServerApplication Server Application
00302 The server in this test creates two data objects, and links one of them to the other, then when a client connect, construction packets are sent to the new client in the bottom up order.
00303 
00304 You should notice the packet-method:
00305 \code
00306 void writePtr( const ServerData * obj );
00307 \endcode
00308 This call will actually just write the unique ID of the data-object, or 0 if the pointer is NULL.
00309 
00310 @include testing/10_pointers/server_main.cpp
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 @page TestPointerUnres 11. Pointers (cyclic: write - read - resolved)
00324 In this test we will create two ServerData objects, both with a pointer to each other. When we send them to the client, the client should update the first object once the second arrives, thereby resolving the "missing pointer".
00325 
00326 @section ClientApplication Client Application
00327 The client application is the same as in the last test.
00328 
00329 @include testing/11_pointers_cyclic/client_main.cpp
00330 
00331 @section ServerApplication Server Application
00332 The server in this test tells the two objects to point at each other, that is the only thing different from this test and the previous.
00333 
00334 @include testing/11_pointers_cyclic/server_main.cpp
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 @page TestPointerUnset 12. Pointer (complex: write - read - unset)
00349 In this test we set up two ServerData objects, one pointing to the other (the small <a href="http://en.wikipedia.org/wiki/Tree_%28graph_theory%29">tree</a>). We then send them bottom up, for easy resolving the pointer. Then on the server we tell the pointing object to no longer point at the pointee, and send an update to all connected clients.
00350 
00351 @section ClientApplication Client Application
00352 The client application is almost the same as in the last test.
00353 
00354 @include testing/12_pointers_write_read_unset/client_main.cpp
00355 
00356 @section ServerApplication Server Application
00357 The server in this test creates the two objects, one pointing at the other. Then after a while it tells the pointing object to point at nothing. And sends out updates on the change.
00358 
00359 @include testing/12_pointers_write_read_unset/server_main.cpp
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 @page TestPointerChange 13. Pointer (complex: write - read - change)
00371 In this test we do much the same as in the last test, except here we change what the objects are pointing at over time. When ever we change something we send updates to the clients.
00372 
00373 @section ClientApplication Client Application
00374 The client application is almost the same as in the last test. Except in this test we print out the PointerPointerTableThingy to make sure that this contains the expected values.
00375 
00376 @include testing/13_pointers_write_read_change/client_main.cpp
00377 
00378 @section ServerApplication Server Application
00379 The server just flips the pointers around every now and then, and sends out updates about it.
00380 
00381 @include testing/13_pointers_write_read_change/server_main.cpp
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 @page TestReadObj 14. Nested Objects (write/read)
00394 In this test we set up a ServerData object, this object has multiple "children" all with baseclass ServerData. When we create the contruct-packet for the client we write these "children" to the packet also. On the client-side we use the method FrameworkPacket::readObject( ClientFramework * f ) to read and construct these "children".
00395 
00396 @section ClientApplication Client Application
00397 In this client application we use 2 datatypes, one that is the child and one that is the parent. What you should notice is the call to:
00398 \code
00399 template<class T>
00400 T * ClientPacket::readObject( ClientFramework * f );
00401 \endcode
00402 This is the method used to read out a "sub-object" from a packet. It should be noted though, that this does NOT have the same posibilities as sending the objects by them selves, and refering them with pointers.
00403 
00404 @include testing/14_nested_objects/client_main.cpp
00405 
00406 @section ServerApplication Server Application
00407 The server also uses two different datatypes. One as the children, and the other as the parent. Note that even though we are actually sending 4 data-objects we nest them all into one packet.
00408 
00409 @include testing/14_nested_objects/server_main.cpp
00410 
00411 
00412 
00413 */

Generated on Mon Feb 6 12:24:50 2006 for Ganef by  doxygen 1.4.4