1/*
2 * Copyright (c) 2011-2014, Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <strings.h>
32#include <iostream>
33#include <stdlib.h>
34#include <sstream>
35#include <assert.h>
36#include <errno.h>
37#include <convert.hpp>
38#include <sstream>
39#include "TestPlatform.h"
40#include "ParameterMgrPlatformConnector.h"
41#include "RemoteProcessorServer.h"
42
43using std::string;
44
45class CParameterMgrPlatformConnectorLogger : public CParameterMgrPlatformConnector::ILogger
46{
47public:
48    CParameterMgrPlatformConnectorLogger() {}
49
50    virtual void log(bool bIsWarning, const string& strLog)
51    {
52
53        if (bIsWarning) {
54
55	    std::cerr << strLog << std::endl;
56        } else {
57
58	    std::cout << strLog << std::endl;
59        }
60    }
61};
62
63CTestPlatform::CTestPlatform(const string& strClass, int iPortNumber, sem_t& exitSemaphore) :
64    _pParameterMgrPlatformConnector(new CParameterMgrPlatformConnector(strClass)),
65    _pParameterMgrPlatformConnectorLogger(new CParameterMgrPlatformConnectorLogger),
66    _exitSemaphore(exitSemaphore)
67{
68    _pCommandHandler = new CCommandHandler(this);
69
70    // Add command parsers
71    _pCommandHandler->addCommandParser("exit", &CTestPlatform::exit,
72                                       0, "", "Exit TestPlatform");
73    _pCommandHandler->addCommandParser(
74        "createExclusiveSelectionCriterionFromStateList",
75        &CTestPlatform::createExclusiveSelectionCriterionFromStateList,
76        2, "<name> <stateList>",
77        "Create inclusive selection criterion from state name list");
78    _pCommandHandler->addCommandParser(
79        "createInclusiveSelectionCriterionFromStateList",
80        &CTestPlatform::createInclusiveSelectionCriterionFromStateList,
81        2, "<name> <stateList>",
82        "Create exclusive selection criterion from state name list");
83
84    _pCommandHandler->addCommandParser(
85        "createExclusiveSelectionCriterion",
86        &CTestPlatform::createExclusiveSelectionCriterion,
87        2, "<name> <nbStates>", "Create inclusive selection criterion");
88    _pCommandHandler->addCommandParser(
89        "createInclusiveSelectionCriterion",
90        &CTestPlatform::createInclusiveSelectionCriterion,
91        2, "<name> <nbStates>", "Create exclusive selection criterion");
92
93    _pCommandHandler->addCommandParser("start", &CTestPlatform::startParameterMgr,
94                                       0, "", "Start ParameterMgr");
95
96    _pCommandHandler->addCommandParser("setCriterionState", &CTestPlatform::setCriterionState,
97                                       2, "<name> <state>",
98                                       "Set the current state of a selection criterion");
99    _pCommandHandler->addCommandParser(
100        "applyConfigurations",
101        &CTestPlatform::applyConfigurations,
102        0, "", "Apply configurations selected by current selection criteria states");
103
104    _pCommandHandler->addCommandParser(
105        "setFailureOnMissingSubsystem",
106        &CTestPlatform::setter<& CParameterMgrPlatformConnector::setFailureOnMissingSubsystem>,
107        1, "true|false", "Set policy for missing subsystems, "
108                         "either abort start or fallback on virtual subsystem.");
109    _pCommandHandler->addCommandParser(
110        "getMissingSubsystemPolicy",
111        &CTestPlatform::getter<& CParameterMgrPlatformConnector::getFailureOnMissingSubsystem>,
112        0, "", "Get policy for missing subsystems, "
113               "either abort start or fallback on virtual subsystem.");
114
115    _pCommandHandler->addCommandParser(
116        "setFailureOnFailedSettingsLoad",
117        &CTestPlatform::setter<& CParameterMgrPlatformConnector::setFailureOnFailedSettingsLoad>,
118        1, "true|false",
119        "Set policy for failed settings load, either abort start or continue without domains.");
120    _pCommandHandler->addCommandParser(
121        "getFailedSettingsLoadPolicy",
122        &CTestPlatform::getter<& CParameterMgrPlatformConnector::getFailureOnFailedSettingsLoad>,
123        0, "",
124        "Get policy for failed settings load, either abort start or continue without domains.");
125
126    _pCommandHandler->addCommandParser(
127        "setValidateSchemasOnStart",
128        &CTestPlatform::setter<& CParameterMgrPlatformConnector::setValidateSchemasOnStart>,
129        1, "true|false",
130        "Set policy for schema validation based on .xsd files (false by default).");
131    _pCommandHandler->addCommandParser(
132        "getValidateSchemasOnStart",
133        &CTestPlatform::getter<& CParameterMgrPlatformConnector::getValidateSchemasOnStart>,
134        0, "",
135        "Get policy for schema validation based on .xsd files.");
136
137    // Create server
138    _pRemoteProcessorServer = new CRemoteProcessorServer(iPortNumber, _pCommandHandler);
139
140    _pParameterMgrPlatformConnector->setLogger(_pParameterMgrPlatformConnectorLogger);
141}
142
143CTestPlatform::~CTestPlatform()
144{
145    delete _pRemoteProcessorServer;
146    delete _pCommandHandler;
147    delete _pParameterMgrPlatformConnectorLogger;
148    delete _pParameterMgrPlatformConnector;
149}
150
151CTestPlatform::CommandReturn CTestPlatform::exit(
152    const IRemoteCommand& remoteCommand, string& strResult)
153{
154    (void)remoteCommand;
155
156    // Release the main blocking semaphore to quit application
157    sem_post(&_exitSemaphore);
158
159    return CTestPlatform::CCommandHandler::EDone;
160}
161
162bool CTestPlatform::load(std::string& strError)
163{
164    // Start remote processor server
165    if (!_pRemoteProcessorServer->start(strError)) {
166
167        strError = "TestPlatform: Unable to start remote processor server: " + strError;
168        return false;
169    }
170
171    return true;
172}
173
174//////////////// Remote command parsers
175/// Selection Criterion
176CTestPlatform::CommandReturn CTestPlatform::createExclusiveSelectionCriterionFromStateList(
177    const IRemoteCommand& remoteCommand, string& strResult)
178{
179    return createExclusiveSelectionCriterionFromStateList(
180        remoteCommand.getArgument(0), remoteCommand, strResult) ?
181           CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::EFailed;
182}
183
184CTestPlatform::CommandReturn CTestPlatform::createInclusiveSelectionCriterionFromStateList(
185    const IRemoteCommand& remoteCommand, string& strResult)
186{
187    return createInclusiveSelectionCriterionFromStateList(
188        remoteCommand.getArgument(0), remoteCommand, strResult) ?
189           CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::EFailed;
190}
191
192CTestPlatform::CommandReturn CTestPlatform::createExclusiveSelectionCriterion(
193    const IRemoteCommand& remoteCommand, string& strResult)
194{
195    return createExclusiveSelectionCriterion(
196        remoteCommand.getArgument(0),
197        strtoul(remoteCommand.getArgument(1).c_str(), NULL, 0),
198        strResult) ?
199           CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::EFailed;
200}
201
202CTestPlatform::CommandReturn CTestPlatform::createInclusiveSelectionCriterion(
203    const IRemoteCommand& remoteCommand, string& strResult)
204{
205    return createInclusiveSelectionCriterion(
206        remoteCommand.getArgument(0),
207        strtoul(remoteCommand.getArgument(1).c_str(), NULL, 0),
208        strResult) ?
209           CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::EFailed;
210}
211
212CTestPlatform::CommandReturn CTestPlatform::startParameterMgr(
213    const IRemoteCommand& remoteCommand, string& strResult)
214{
215    (void)remoteCommand;
216
217    return _pParameterMgrPlatformConnector->start(strResult) ?
218           CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::EFailed;
219}
220
221template <CTestPlatform::setter_t setFunction>
222CTestPlatform::CommandReturn CTestPlatform::setter(
223    const IRemoteCommand& remoteCommand, string& strResult)
224{
225    const string& strAbort = remoteCommand.getArgument(0);
226
227    bool bFail;
228
229    if(!convertTo(strAbort, bFail)) {
230        return CTestPlatform::CCommandHandler::EShowUsage;
231    }
232
233    return (_pParameterMgrPlatformConnector->*setFunction)(bFail, strResult) ?
234           CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::EFailed;
235}
236
237template <CTestPlatform::getter_t getFunction>
238CTestPlatform::CommandReturn CTestPlatform::getter(
239    const IRemoteCommand& remoteCommand, string& strResult)
240{
241    (void)remoteCommand;
242
243    strResult = (_pParameterMgrPlatformConnector->*getFunction)() ? "true" : "false";
244
245    return CTestPlatform::CCommandHandler::ESucceeded;
246}
247
248CTestPlatform::CommandReturn CTestPlatform::setCriterionState(
249    const IRemoteCommand& remoteCommand, string& strResult)
250{
251
252    bool bSuccess;
253
254    const char* pcState = remoteCommand.getArgument(1).c_str();
255
256    char* pcStrEnd;
257
258    // Reset errno to check if it is updated during the conversion (strtol/strtoul)
259    errno = 0;
260
261    uint32_t state = strtoul(pcState, &pcStrEnd, 0);
262
263    if (!errno && (*pcStrEnd == '\0')) {
264        // Sucessfull conversion, set criterion state by numerical state
265        bSuccess = setCriterionState(remoteCommand.getArgument(0), state, strResult);
266
267    } else {
268        // Conversion failed, set criterion state by lexical state
269        bSuccess = setCriterionStateByLexicalSpace(remoteCommand, strResult);
270    }
271
272    return bSuccess ? CTestPlatform::CCommandHandler::EDone : CTestPlatform::CCommandHandler::
273           EFailed;
274
275}
276
277CTestPlatform::CommandReturn CTestPlatform::applyConfigurations(const IRemoteCommand& remoteCommand,
278                                                                string& strResult)
279{
280    (void)remoteCommand;
281    (void)strResult;
282
283    _pParameterMgrPlatformConnector->applyConfigurations();
284
285    return CTestPlatform::CCommandHandler::EDone;
286}
287
288//////////////// Remote command handlers
289
290bool CTestPlatform::createExclusiveSelectionCriterionFromStateList(
291                                                                const string& strName,
292                                                                const IRemoteCommand& remoteCommand,
293                                                                string& strResult)
294{
295
296    assert(_pParameterMgrPlatformConnector != NULL);
297
298    ISelectionCriterionTypeInterface* pCriterionType =
299        _pParameterMgrPlatformConnector->createSelectionCriterionType(false);
300
301    assert(pCriterionType != NULL);
302
303    uint32_t uiNbStates = remoteCommand.getArgumentCount() - 1;
304    uint32_t uiState;
305
306    for (uiState = 0; uiState < uiNbStates; uiState++) {
307
308        const std::string& strValue = remoteCommand.getArgument(uiState + 1);
309
310        if (!pCriterionType->addValuePair(uiState, strValue)) {
311
312            strResult = "Unable to add value: " + strValue;
313
314            return false;
315        }
316    }
317
318    _pParameterMgrPlatformConnector->createSelectionCriterion(strName, pCriterionType);
319
320    return true;
321}
322
323bool CTestPlatform::createInclusiveSelectionCriterionFromStateList(
324                                                                const string& strName,
325                                                                const IRemoteCommand& remoteCommand,
326                                                                string& strResult)
327{
328    assert(_pParameterMgrPlatformConnector != NULL);
329
330    ISelectionCriterionTypeInterface* pCriterionType =
331        _pParameterMgrPlatformConnector->createSelectionCriterionType(true);
332
333    assert(pCriterionType != NULL);
334
335    uint32_t uiNbStates = remoteCommand.getArgumentCount() - 1;
336
337    if (uiNbStates > 32) {
338
339        strResult = "Maximum number of states for inclusive criterion is 32";
340
341        return false;
342    }
343
344    uint32_t uiState;
345
346    for (uiState = 0; uiState < uiNbStates; uiState++) {
347
348        const std::string& strValue = remoteCommand.getArgument(uiState + 1);
349
350        if (!pCriterionType->addValuePair(0x1 << uiState, strValue)) {
351
352            strResult = "Unable to add value: " + strValue;
353
354            return false;
355        }
356    }
357
358    _pParameterMgrPlatformConnector->createSelectionCriterion(strName, pCriterionType);
359
360    return true;
361}
362
363
364bool CTestPlatform::createExclusiveSelectionCriterion(const string& strName,
365                                                      uint32_t uiNbStates,
366                                                      string& strResult)
367{
368    ISelectionCriterionTypeInterface* pCriterionType =
369        _pParameterMgrPlatformConnector->createSelectionCriterionType(false);
370
371    uint32_t uistate;
372
373    for (uistate = 0; uistate < uiNbStates; uistate++) {
374
375	std::ostringstream ostrValue;
376
377        ostrValue << "State_";
378        ostrValue << uistate;
379
380        if (!pCriterionType->addValuePair(uistate, ostrValue.str())) {
381
382            strResult = "Unable to add value: " + ostrValue.str();
383
384            return false;
385        }
386    }
387
388    _pParameterMgrPlatformConnector->createSelectionCriterion(strName, pCriterionType);
389
390    return true;
391}
392
393bool CTestPlatform::createInclusiveSelectionCriterion(const string& strName,
394                                                      uint32_t uiNbStates,
395                                                      string& strResult)
396{
397    ISelectionCriterionTypeInterface* pCriterionType =
398        _pParameterMgrPlatformConnector->createSelectionCriterionType(true);
399
400    if (uiNbStates > 32) {
401
402        strResult = "Maximum number of states for inclusive criterion is 32";
403
404        return false;
405    }
406
407    uint32_t uiState;
408
409    for (uiState = 0; uiState < uiNbStates; uiState++) {
410
411	std::ostringstream ostrValue;
412
413        ostrValue << "State_0x";
414        ostrValue << (0x1 << uiState);
415
416        if (!pCriterionType->addValuePair(0x1 << uiState, ostrValue.str())) {
417
418            strResult = "Unable to add value: " + ostrValue.str();
419
420            return false;
421        }
422    }
423
424    _pParameterMgrPlatformConnector->createSelectionCriterion(strName, pCriterionType);
425
426    return true;
427}
428
429bool CTestPlatform::setCriterionState(const string& strName, uint32_t uiState, string& strResult)
430{
431    ISelectionCriterionInterface* pCriterion =
432        _pParameterMgrPlatformConnector->getSelectionCriterion(strName);
433
434    if (!pCriterion) {
435
436        strResult = "Unable to retrieve selection criterion: " + strName;
437
438        return false;
439    }
440
441    pCriterion->setCriterionState(uiState);
442
443    return true;
444}
445
446bool CTestPlatform::setCriterionStateByLexicalSpace(const IRemoteCommand& remoteCommand,
447                                                    string& strResult)
448{
449
450    // Get criterion name
451    std::string strCriterionName = remoteCommand.getArgument(0);
452
453    ISelectionCriterionInterface* pCriterion =
454        _pParameterMgrPlatformConnector->getSelectionCriterion(strCriterionName);
455
456    if (!pCriterion) {
457
458        strResult = "Unable to retrieve selection criterion: " + strCriterionName;
459
460        return false;
461    }
462
463    // Get criterion type
464    const ISelectionCriterionTypeInterface* pCriterionType = pCriterion->getCriterionType();
465
466    // Get substate number, the first argument (index 0) is the criterion name
467    uint32_t uiNbSubStates = remoteCommand.getArgumentCount() - 1;
468
469    // Check that exclusive criterion has only one substate
470    if (!pCriterionType->isTypeInclusive() && uiNbSubStates != 1) {
471
472        strResult = "Exclusive criterion " + strCriterionName + " can only have one state";
473
474        return false;
475    }
476
477    /// Translate lexical state to numerical state
478    int iNumericalState = 0;
479    uint32_t uiLexicalSubStateIndex;
480
481    // Parse lexical substates
482    std::string strLexicalState = "";
483
484    for (uiLexicalSubStateIndex = 1;
485         uiLexicalSubStateIndex <= uiNbSubStates;
486         uiLexicalSubStateIndex++) {
487        /*
488         * getNumericalValue method from ISelectionCriterionTypeInterface strip his parameter
489         * first parameter based on | sign. In case that the user uses multiple parameters
490         * to set InclusiveCriterion value, we aggregate all desired values to be sure
491         * they will be handled correctly.
492         */
493        if (uiLexicalSubStateIndex != 1) {
494            strLexicalState += "|";
495        }
496        strLexicalState += remoteCommand.getArgument(uiLexicalSubStateIndex);
497    }
498
499    // Translate lexical to numerical substate
500    if (!pCriterionType->getNumericalValue(strLexicalState, iNumericalState)) {
501
502        strResult = "Unable to find lexical state \""
503            + strLexicalState + "\" in criteria " + strCriterionName;
504
505        return false;
506    }
507
508    // Set criterion new state
509    pCriterion->setCriterionState(iNumericalState);
510
511    return true;
512}
513