/[svn]/linuxsampler/trunk/src/testcases/LSCPTest.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/testcases/LSCPTest.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 211 by schoenebeck, Sun Jul 25 23:27:41 2004 UTC revision 224 by schoenebeck, Sat Aug 21 15:31:36 2004 UTC
# Line 1  Line 1 
1  #include "LSCPTest.h"  #include "LSCPTest.h"
2    
3    #include "../common/global.h"
4    #include "../common/optional.h"
5    
6  #include <iostream>  #include <iostream>
7  #include <stdio.h>  #include <stdio.h>
8  #include <stdlib.h>  #include <stdlib.h>
9    #include <unistd.h>
10    #include <fcntl.h>
11    #include <sys/types.h>
12    #include <sys/socket.h>
13    
14  CPPUNIT_TEST_SUITE_REGISTRATION(LSCPTest);  CPPUNIT_TEST_SUITE_REGISTRATION(LSCPTest);
15    
# Line 14  CPPUNIT_TEST_SUITE_REGISTRATION(LSCPTest Line 21  CPPUNIT_TEST_SUITE_REGISTRATION(LSCPTest
21  static Sampler*    pSampler    = NULL;  static Sampler*    pSampler    = NULL;
22  static LSCPServer* pLSCPServer = NULL;  static LSCPServer* pLSCPServer = NULL;
23  static int         hSocket     = -1;  static int         hSocket     = -1;
24  static FILE*       hServerIn   = NULL;  
25    /// Returns first token from \a sentence and removes that token (and evtl. delimiter) from \a sentence.
26    static optional<string> __ExtractFirstToken(string* pSentence, const string Delimiter) {
27        if (*pSentence == "") return optional<string>::nothing;
28    
29        string::size_type pos = pSentence->find(Delimiter);
30    
31        // if sentence has only one token
32        if (pos == string::npos) {
33            string token = *pSentence;
34            *pSentence = "";
35            return token;
36        }
37    
38        // sentence has more than one token, so extract the first token
39        string token = pSentence->substr(0, pos);
40        *pSentence   = pSentence->replace(0, pos + 1, "");
41        return token;
42    }
43    
44  // split the multi line response string into the individual lines and remove the last (delimiter) line and the line feed characters in all lines  // split the multi line response string into the individual lines and remove the last (delimiter) line and the line feed characters in all lines
45  static vector<string> __ConvertMultiLineMessage(string msg) {  static vector<string> __ConvertMultiLineMessage(string msg) {
# Line 107  bool LSCPTest::connectToLSCPServer() { Line 132  bool LSCPTest::connectToLSCPServer() {
132          return false;          return false;
133      }      }
134    
135      hServerIn = fdopen(hSocket, "r");      // set non-blocking mode
136        int socket_flags = fcntl(hSocket, F_GETFL, 0);
137        fcntl(hSocket, F_SETFL, socket_flags | O_NONBLOCK);
138    
139      return true;      return true;
140  }  }
141    
142  bool LSCPTest::closeConnectionToLSCPServer() {  bool LSCPTest::closeConnectionToLSCPServer() {
143      //cout << "closeConnectionToLSCPServer()\n" << flush;      //cout << "closeConnectionToLSCPServer()\n" << flush;
     hServerIn = NULL;  
144      if (hSocket >= 0) {      if (hSocket >= 0) {
145          close(hSocket);          close(hSocket);
146          hSocket = -1;          hSocket = -1;
# Line 132  void LSCPTest::sendCommandToLSCPServer(s Line 158  void LSCPTest::sendCommandToLSCPServer(s
158      send(hSocket, cmd.c_str(), cmd.length(), 0);      send(hSocket, cmd.c_str(), cmd.length(), 0);
159  }  }
160    
161  // wait until LSCP server answers with a single line answer  // wait until LSCP server answers with a single line answer (throws LinuxSamplerException if optional timeout exceeded)
162  string LSCPTest::receiveSingleLineAnswerFromLSCPServer() {  string LSCPTest::receiveSingleLineAnswerFromLSCPServer(uint timeout_seconds) throw (LinuxSamplerException) {
163      string msg = receiveAnswerFromLSCPServer("\n");      string msg = receiveAnswerFromLSCPServer("\n", timeout_seconds);
164        // remove carriage return characters
165        string::size_type p = msg.find('\r');
166        for (; p != string::npos; p = msg.find(p, '\r')) msg.erase(p, 1);
167      // remove the line feed at the end      // remove the line feed at the end
168      static const string linedelimiter = "\r\n";      static const string linedelimiter = "\n";
169      string::size_type pos = msg.rfind(linedelimiter);      string::size_type pos = msg.rfind(linedelimiter);
170      return msg.substr(0, pos);      return msg.substr(0, pos);
171  }  }
172    
173  // wait until LSCP server answers with a multi line answer  /// wait until LSCP server answers with a multi line answer (throws LinuxSamplerException if optional timeout exceeded)
174  vector<string> LSCPTest::receiveMultiLineAnswerFromLSCPServer() {  vector<string> LSCPTest::receiveMultiLineAnswerFromLSCPServer(uint timeout_seconds) throw (LinuxSamplerException) {
175      string msg = receiveAnswerFromLSCPServer("\n.\r\n");      string msg = receiveAnswerFromLSCPServer("\n.\r\n", timeout_seconds);
176      return __ConvertMultiLineMessage(msg);      return __ConvertMultiLineMessage(msg);
177  }  }
178    
179  // wait until LSCP server answers with the given \a delimiter token at the end  void LSCPTest::clearInputBuffer() {
180  string LSCPTest::receiveAnswerFromLSCPServer(string delimiter) {      char c;
181      if (!hServerIn) {      while (recv(hSocket, &c, 1, 0) > 0);
182          cout << "receiveAnswerFromLSCPServer() error: client socket not ready\n" << flush;  }
183          return "";  
184      }  /// wait until LSCP server answers with the given \a delimiter token at the end (throws LinuxSamplerException if optional timeout exceeded or socket error occured)
185    string LSCPTest::receiveAnswerFromLSCPServer(string delimiter, uint timeout_seconds) throw (LinuxSamplerException) {
186      string message;      string message;
187      char c;      char c;
188      while ((c = fgetc(hServerIn)) != EOF) {      fd_set sockSet;
189        timeval timeout;
190    
191        while (true) {
192            if (timeout_seconds) {
193                FD_ZERO(&sockSet);
194                FD_SET(hSocket, &sockSet);
195                timeout.tv_sec  = timeout_seconds;
196                timeout.tv_usec = 0;
197                int res = select(hSocket + 1, &sockSet, NULL, NULL, &timeout);
198                if (!res) { // if timeout exceeded
199                    if (!message.size()) throw LinuxSamplerException("LSCPTest::receiveAnswerFromLSCPServer(): timeout (" + ToString(timeout_seconds) + "s) exceeded, no answer received");
200                    else                 throw LinuxSamplerException("LSCPTest::receiveAnswerFromLSCPServer(): timeout (" + ToString(timeout_seconds) + "s) exceeded waiting for expected answer (end), received answer: \'" + message + "\'");
201                }
202                else if (res < 0) {
203                    throw LinuxSamplerException("LSCPTest::receiveAnswerFromLSCPServer(): select error");
204                }
205            }
206    
207            // there's something to read, so read one character
208            int res = recv(hSocket, &c, 1, 0);
209            if (!res) throw LinuxSamplerException("LSCPTest::receiveAnswerFromLSCPServer(): connection to LSCP server closed");
210            else if (res < 0) {
211                switch(errno) {
212                    case EBADF:
213                        throw LinuxSamplerException("The argument s is an invalid descriptor");
214                    case ECONNREFUSED:
215                        throw LinuxSamplerException("A remote host refused to allow the network connection (typically because it is not running the requested service).");
216                    case ENOTCONN:
217                        throw LinuxSamplerException("The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).");
218                    case ENOTSOCK:
219                        throw LinuxSamplerException("The argument s does not refer to a socket.");
220                    case EAGAIN:
221                        continue;
222                        //throw LinuxSamplerException("The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.");
223                    case EINTR:
224                        throw LinuxSamplerException("The receive was interrupted by delivery of a signal before any data were available.");
225                    case EFAULT:
226                        throw LinuxSamplerException("The receive buffer pointer(s) point outside the process's address space.");
227                    case EINVAL:
228                        throw LinuxSamplerException("Invalid argument passed.");
229                    case ENOMEM:
230                        throw LinuxSamplerException("Could not allocate memory for recvmsg.");
231                    default:
232                        throw LinuxSamplerException("Unknown recv() error.");
233                }
234            }
235    
236          message += c;          message += c;
237          string::size_type pos = message.rfind(delimiter); // ouch, but this is only a test case, right? ;)          string::size_type pos = message.rfind(delimiter); // ouch, but this is only a test case, right? ;)
238          if (pos != string::npos) return message;          if (pos != string::npos) return message;
239      }      }
     cout << "receiveAnswerFromLSCPServer() error: EOF reached\n" << flush;  
     return "";  
240  }  }
241    
242    
# Line 174  void LSCPTest::setUp() { Line 249  void LSCPTest::setUp() {
249  }  }
250    
251  void LSCPTest::tearDown() {  void LSCPTest::tearDown() {
252        clearInputBuffer(); // to avoid that the next test reads an answer from a previous test
253  }  }
254    
255    
# Line 263  void LSCPTest::test_REMOVE_CHANNEL() { Line 339  void LSCPTest::test_REMOVE_CHANNEL() {
339      CPPUNIT_ASSERT(true); // success      CPPUNIT_ASSERT(true); // success
340  }  }
341    
342    // Check "GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO" LSCP command.
343    void LSCPTest::test_GET_AUDIO_OUTPUT_CHANNEL_PARAMETER_INFO() {
344        // first check if there's already an audio output device created
345        sendCommandToLSCPServer("GET AUDIO_OUTPUT_DEVICES");
346        string answer = receiveSingleLineAnswerFromLSCPServer();
347        int devices   = atoi(answer.c_str());
348        CPPUNIT_ASSERT(devices >= 0);
349        if (!devices) { // if there's no audio output device yet, try to create one
350            sendCommandToLSCPServer("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");
351            string drivers = receiveSingleLineAnswerFromLSCPServer();
352            CPPUNIT_ASSERT(drivers.size());
353    
354            // iterate through all available drivers until device creation was successful
355            do {
356                optional<string> driver = __ExtractFirstToken(&drivers, ",");
357                CPPUNIT_ASSERT(driver);
358    
359                sendCommandToLSCPServer("CREATE AUDIO_OUTPUT_DEVICE " + *driver);
360                answer = receiveSingleLineAnswerFromLSCPServer(120); // wait 2 minutes for an answer
361            } while (answer != "OK[0]");
362        }
363    
364        // now we can check the "GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO" command
365        const uint timeout_seconds = 2;
366        sendCommandToLSCPServer("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO 0 0 NAME");
367        vector<string> vAnswer = receiveMultiLineAnswerFromLSCPServer(timeout_seconds);
368        CPPUNIT_ASSERT(vAnswer.size() >= 4); // should at least contain tags TYPE, DESCRIPTION, FIX and MULTIPLICITY
369    
370        sendCommandToLSCPServer("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO 0 0 IS_MIX_CHANNEL");
371        vAnswer = receiveMultiLineAnswerFromLSCPServer(timeout_seconds);
372        CPPUNIT_ASSERT(vAnswer.size() >= 4); // should at least contain tags TYPE, DESCRIPTION, FIX and MULTIPLICITY
373    }
374    
375    // Check "SET ECHO" LSCP command.
376    void LSCPTest::test_SET_ECHO() {
377        // enable echo mode
378        sendCommandToLSCPServer("SET ECHO 1");
379        CPPUNIT_ASSERT(receiveSingleLineAnswerFromLSCPServer() == "OK");
380    
381        // check if commands will actually be echoed now
382        sendCommandToLSCPServer("GET CHANNELS"); // send an arbitrary command
383        CPPUNIT_ASSERT(receiveSingleLineAnswerFromLSCPServer(2) == "GET CHANNELS");
384        receiveSingleLineAnswerFromLSCPServer(2); // throws exception if no answer received after 2s (usually we expect the answer from our command here)
385    
386        // disable echo mode
387        sendCommandToLSCPServer("SET ECHO 0");
388        CPPUNIT_ASSERT(receiveSingleLineAnswerFromLSCPServer() == "SET ECHO 0"); // this will be echoed though
389        CPPUNIT_ASSERT(receiveSingleLineAnswerFromLSCPServer() == "OK");
390    
391        // check if commands will not be echoed now
392        sendCommandToLSCPServer("GET CHANNELS");
393        CPPUNIT_ASSERT(receiveSingleLineAnswerFromLSCPServer() != "GET CHANNELS");
394    }
395    
396  // Check if we can shutdown the LSCP Server without problems.  // Check if we can shutdown the LSCP Server without problems.
397  void LSCPTest::testShutdownLSCPServer() {  void LSCPTest::testShutdownLSCPServer() {
398      //cout << "testShutdownLSCPServer()\n" << flush;      //cout << "testShutdownLSCPServer()\n" << flush;

Legend:
Removed from v.211  
changed lines
  Added in v.224

  ViewVC Help
Powered by ViewVC