1/*
2 * Copyright (c) 2011-2015, 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 <stdlib.h>
32#include <sstream>
33#include <assert.h>
34#include <errno.h>
35#include <convert.hpp>
36#include <sstream>
37#include "TestPlatform.h"
38
39using std::string;
40
41CTestPlatform::CTestPlatform(const string &strClass, uint16_t iPortNumber)
42    : mParameterMgrPlatformConnector(strClass), mLogger(), mRemoteProcessorServer(iPortNumber)
43{
44    mParameterMgrPlatformConnector.setLogger(&mLogger);
45}
46
47CTestPlatform::~CTestPlatform()
48{
49}
50
51CTestPlatform::CommandReturn CTestPlatform::exit(const IRemoteCommand & /*command*/,
52                                                 string & /*strResult*/)
53{
54    mRemoteProcessorServer.stop();
55
56    return CTestPlatform::CCommandHandler::EDone;
57}
58
59bool CTestPlatform::run(std::string &strError)
60{
61    // Start remote processor server
62    if (!mRemoteProcessorServer.start(strError)) {
63
64        strError = "TestPlatform: Unable to start remote processor server: " + strError;
65        return false;
66    }
67
68    CCommandHandler commandHandler(this);
69
70    // Add command parsers
71    commandHandler.addCommandParser("exit", &CTestPlatform::exit, 0, "", "Exit TestPlatform");
72    commandHandler.addCommandParser("createExclusiveSelectionCriterionFromStateList",
73                                    &CTestPlatform::createExclusiveSelectionCriterionFromStateList,
74                                    2, "<name> <stateList>",
75                                    "Create inclusive selection criterion from state name list");
76    commandHandler.addCommandParser("createInclusiveSelectionCriterionFromStateList",
77                                    &CTestPlatform::createInclusiveSelectionCriterionFromStateList,
78                                    2, "<name> <stateList>",
79                                    "Create exclusive selection criterion from state name list");
80
81    commandHandler.addCommandParser("createExclusiveSelectionCriterion",
82                                    &CTestPlatform::createExclusiveSelectionCriterion, 2,
83                                    "<name> <nbStates>", "Create inclusive selection criterion");
84    commandHandler.addCommandParser("createInclusiveSelectionCriterion",
85                                    &CTestPlatform::createInclusiveSelectionCriterion, 2,
86                                    "<name> <nbStates>", "Create exclusive selection criterion");
87
88    commandHandler.addCommandParser("start", &CTestPlatform::startParameterMgr, 0, "",
89                                    "Start ParameterMgr");
90
91    commandHandler.addCommandParser("setCriterionState", &CTestPlatform::setCriterionState, 2,
92                                    "<name> <state>",
93                                    "Set the current state of a selection criterion");
94    commandHandler.addCommandParser(
95        "applyConfigurations", &CTestPlatform::applyConfigurations, 0, "",
96        "Apply configurations selected by current selection criteria states");
97
98    commandHandler.addCommandParser(
99        "setFailureOnMissingSubsystem",
100        &CTestPlatform::setter<&CParameterMgrPlatformConnector::setFailureOnMissingSubsystem>, 1,
101        "true|false", "Set policy for missing subsystems, "
102                      "either abort start or fallback on virtual subsystem.");
103    commandHandler.addCommandParser(
104        "getMissingSubsystemPolicy",
105        &CTestPlatform::getter<&CParameterMgrPlatformConnector::getFailureOnMissingSubsystem>, 0,
106        "", "Get policy for missing subsystems, "
107            "either abort start or fallback on virtual subsystem.");
108
109    commandHandler.addCommandParser(
110        "setFailureOnFailedSettingsLoad",
111        &CTestPlatform::setter<&CParameterMgrPlatformConnector::setFailureOnFailedSettingsLoad>, 1,
112        "true|false",
113        "Set policy for failed settings load, either abort start or continue without domains.");
114    commandHandler.addCommandParser(
115        "getFailedSettingsLoadPolicy",
116        &CTestPlatform::getter<&CParameterMgrPlatformConnector::getFailureOnFailedSettingsLoad>, 0,
117        "", "Get policy for failed settings load, either abort start or continue without domains.");
118
119    commandHandler.addCommandParser(
120        "setValidateSchemasOnStart",
121        &CTestPlatform::setter<&CParameterMgrPlatformConnector::setValidateSchemasOnStart>, 1,
122        "true|false", "Set policy for schema validation based on .xsd files (false by default).");
123    commandHandler.addCommandParser(
124        "getValidateSchemasOnStart",
125        &CTestPlatform::getter<&CParameterMgrPlatformConnector::getValidateSchemasOnStart>, 0, "",
126        "Get policy for schema validation based on .xsd files.");
127
128    commandHandler.addCommandParser("getSchemaUri", &CTestPlatform::getSchemaUri, 0, "",
129                                    "Get the directory where schemas can be found.");
130    commandHandler.addCommandParser("setSchemaUri", &CTestPlatform::setSchemaUri, 1, "<directory>",
131                                    "Set the directory where schemas can be found.");
132
133    return mRemoteProcessorServer.process(commandHandler);
134}
135
136//////////////// Remote command parsers
137/// Selection Criterion
138CTestPlatform::CommandReturn CTestPlatform::createExclusiveSelectionCriterionFromStateList(
139    const IRemoteCommand &remoteCommand, string &strResult)
140{
141    return createExclusiveSelectionCriterionFromStateList(remoteCommand.getArgument(0),
142                                                          remoteCommand, strResult)
143               ? CTestPlatform::CCommandHandler::EDone
144               : CTestPlatform::CCommandHandler::EFailed;
145}
146
147CTestPlatform::CommandReturn CTestPlatform::createInclusiveSelectionCriterionFromStateList(
148    const IRemoteCommand &remoteCommand, string &strResult)
149{
150    return createInclusiveSelectionCriterionFromStateList(remoteCommand.getArgument(0),
151                                                          remoteCommand, strResult)
152               ? CTestPlatform::CCommandHandler::EDone
153               : CTestPlatform::CCommandHandler::EFailed;
154}
155
156CTestPlatform::CommandReturn CTestPlatform::createExclusiveSelectionCriterion(
157    const IRemoteCommand &remoteCommand, string &strResult)
158{
159    return createExclusiveSelectionCriterion(remoteCommand.getArgument(0),
160                                             strtoul(remoteCommand.getArgument(1).c_str(), NULL, 0),
161                                             strResult)
162               ? CTestPlatform::CCommandHandler::EDone
163               : CTestPlatform::CCommandHandler::EFailed;
164}
165
166CTestPlatform::CommandReturn CTestPlatform::createInclusiveSelectionCriterion(
167    const IRemoteCommand &remoteCommand, string &strResult)
168{
169    return createInclusiveSelectionCriterion(remoteCommand.getArgument(0),
170                                             strtoul(remoteCommand.getArgument(1).c_str(), NULL, 0),
171                                             strResult)
172               ? CTestPlatform::CCommandHandler::EDone
173               : CTestPlatform::CCommandHandler::EFailed;
174}
175
176CTestPlatform::CommandReturn CTestPlatform::startParameterMgr(
177    const IRemoteCommand & /*remoteCommand*/, string &strResult)
178{
179    return mParameterMgrPlatformConnector.start(strResult)
180               ? CTestPlatform::CCommandHandler::EDone
181               : CTestPlatform::CCommandHandler::EFailed;
182}
183
184template <CTestPlatform::setter_t setFunction>
185CTestPlatform::CommandReturn CTestPlatform::setter(const IRemoteCommand &remoteCommand,
186                                                   string &strResult)
187{
188    const string &strAbort = remoteCommand.getArgument(0);
189
190    bool bFail;
191
192    if (!convertTo(strAbort, bFail)) {
193        return CTestPlatform::CCommandHandler::EShowUsage;
194    }
195
196    return (mParameterMgrPlatformConnector.*setFunction)(bFail, strResult)
197               ? CTestPlatform::CCommandHandler::EDone
198               : CTestPlatform::CCommandHandler::EFailed;
199}
200
201template <CTestPlatform::getter_t getFunction>
202CTestPlatform::CommandReturn CTestPlatform::getter(const IRemoteCommand & /*command*/,
203                                                   string &strResult)
204{
205    strResult = (mParameterMgrPlatformConnector.*getFunction)() ? "true" : "false";
206
207    return CTestPlatform::CCommandHandler::ESucceeded;
208}
209
210CTestPlatform::CommandReturn CTestPlatform::getSchemaUri(const IRemoteCommand & /*remotecommand*/,
211                                                         string &result)
212{
213    result = mParameterMgrPlatformConnector.getSchemaUri();
214    return CTestPlatform::CCommandHandler::EDone;
215}
216
217CTestPlatform::CommandReturn CTestPlatform::setSchemaUri(const IRemoteCommand &remotecommand,
218                                                         string & /*result*/)
219{
220    mParameterMgrPlatformConnector.setSchemaUri(remotecommand.getArgument(0));
221    return CTestPlatform::CCommandHandler::EDone;
222}
223
224CTestPlatform::CommandReturn CTestPlatform::setCriterionState(const IRemoteCommand &remoteCommand,
225                                                              string &strResult)
226{
227
228    bool bSuccess;
229
230    uint32_t state;
231
232    if (convertTo(remoteCommand.getArgument(1), state)) {
233        // Sucessfull conversion, set criterion state by numerical state
234        bSuccess = setCriterionState(remoteCommand.getArgument(0), state, strResult);
235
236    } else {
237        // Conversion failed, set criterion state by lexical state
238        bSuccess = setCriterionStateByLexicalSpace(remoteCommand, strResult);
239    }
240
241    return bSuccess ? CTestPlatform::CCommandHandler::EDone
242                    : CTestPlatform::CCommandHandler::EFailed;
243}
244
245CTestPlatform::CommandReturn CTestPlatform::applyConfigurations(const IRemoteCommand & /*command*/,
246                                                                string & /*strResult*/)
247{
248    mParameterMgrPlatformConnector.applyConfigurations();
249
250    return CTestPlatform::CCommandHandler::EDone;
251}
252
253//////////////// Remote command handlers
254
255bool CTestPlatform::createExclusiveSelectionCriterionFromStateList(
256    const string &strName, const IRemoteCommand &remoteCommand, string &strResult)
257{
258    ISelectionCriterionTypeInterface *pCriterionType =
259        mParameterMgrPlatformConnector.createSelectionCriterionType(false);
260
261    assert(pCriterionType != NULL);
262
263    size_t nbStates = remoteCommand.getArgumentCount() - 1;
264
265    for (size_t state = 0; state < nbStates; state++) {
266
267        const std::string &strValue = remoteCommand.getArgument(state + 1);
268
269        // FIXME state type vs addValuePair params
270        if (!pCriterionType->addValuePair(int(state), strValue, strResult)) {
271
272            strResult = "Unable to add value: " + strValue + ": " + strResult;
273
274            return false;
275        }
276    }
277
278    mParameterMgrPlatformConnector.createSelectionCriterion(strName, pCriterionType);
279
280    return true;
281}
282
283bool CTestPlatform::createInclusiveSelectionCriterionFromStateList(
284    const string &strName, const IRemoteCommand &remoteCommand, string &strResult)
285{
286    ISelectionCriterionTypeInterface *pCriterionType =
287        mParameterMgrPlatformConnector.createSelectionCriterionType(true);
288
289    assert(pCriterionType != NULL);
290
291    size_t nbStates = remoteCommand.getArgumentCount() - 1;
292
293    for (size_t state = 0; state < nbStates; state++) {
294
295        const std::string &strValue = remoteCommand.getArgument(state + 1);
296
297        if (!pCriterionType->addValuePair(0x1 << state, strValue, strResult)) {
298
299            strResult = "Unable to add value: " + strValue + ": " + strResult;
300
301            return false;
302        }
303    }
304
305    mParameterMgrPlatformConnector.createSelectionCriterion(strName, pCriterionType);
306
307    return true;
308}
309
310bool CTestPlatform::createExclusiveSelectionCriterion(const string &strName, size_t nbStates,
311                                                      string &strResult)
312{
313    ISelectionCriterionTypeInterface *pCriterionType =
314        mParameterMgrPlatformConnector.createSelectionCriterionType(false);
315
316    for (size_t state = 0; state < nbStates; state++) {
317
318        std::ostringstream ostrValue;
319
320        ostrValue << "State_";
321        ostrValue << state;
322
323        // FIXME state type vs addValuePair params
324        if (!pCriterionType->addValuePair(int(state), ostrValue.str(), strResult)) {
325
326            strResult = "Unable to add value: " + ostrValue.str() + ": " + strResult;
327
328            return false;
329        }
330    }
331
332    mParameterMgrPlatformConnector.createSelectionCriterion(strName, pCriterionType);
333
334    return true;
335}
336
337bool CTestPlatform::createInclusiveSelectionCriterion(const string &strName, size_t nbStates,
338                                                      string &strResult)
339{
340    ISelectionCriterionTypeInterface *pCriterionType =
341        mParameterMgrPlatformConnector.createSelectionCriterionType(true);
342
343    for (size_t state = 0; state < nbStates; state++) {
344
345        std::ostringstream ostrValue;
346
347        ostrValue << "State_0x";
348        ostrValue << (0x1 << state);
349
350        if (!pCriterionType->addValuePair(0x1 << state, ostrValue.str(), strResult)) {
351
352            strResult = "Unable to add value: " + ostrValue.str() + ": " + strResult;
353
354            return false;
355        }
356    }
357
358    mParameterMgrPlatformConnector.createSelectionCriterion(strName, pCriterionType);
359
360    return true;
361}
362
363bool CTestPlatform::setCriterionState(const string &strName, uint32_t uiState, string &strResult)
364{
365    ISelectionCriterionInterface *pCriterion =
366        mParameterMgrPlatformConnector.getSelectionCriterion(strName);
367
368    if (!pCriterion) {
369
370        strResult = "Unable to retrieve selection criterion: " + strName;
371
372        return false;
373    }
374
375    pCriterion->setCriterionState(uiState);
376
377    return true;
378}
379
380bool CTestPlatform::setCriterionStateByLexicalSpace(const IRemoteCommand &remoteCommand,
381                                                    string &strResult)
382{
383
384    // Get criterion name
385    std::string strCriterionName = remoteCommand.getArgument(0);
386
387    ISelectionCriterionInterface *pCriterion =
388        mParameterMgrPlatformConnector.getSelectionCriterion(strCriterionName);
389
390    if (!pCriterion) {
391
392        strResult = "Unable to retrieve selection criterion: " + strCriterionName;
393
394        return false;
395    }
396
397    // Get criterion type
398    const ISelectionCriterionTypeInterface *pCriterionType = pCriterion->getCriterionType();
399
400    // Get substate number, the first argument (index 0) is the criterion name
401    size_t nbSubStates = remoteCommand.getArgumentCount() - 1;
402
403    // Check that exclusive criterion has only one substate
404    if (!pCriterionType->isTypeInclusive() && nbSubStates != 1) {
405
406        strResult = "Exclusive criterion " + strCriterionName + " can only have one state";
407
408        return false;
409    }
410
411    /// Translate lexical state to numerical state
412    int iNumericalState = 0;
413    size_t lexicalSubStateIndex;
414
415    // Parse lexical substates
416    std::string strLexicalState = "";
417
418    for (lexicalSubStateIndex = 1; lexicalSubStateIndex <= nbSubStates; lexicalSubStateIndex++) {
419        /*
420         * getNumericalValue method from ISelectionCriterionTypeInterface strip his parameter
421         * first parameter based on | sign. In case that the user uses multiple parameters
422         * to set InclusiveCriterion value, we aggregate all desired values to be sure
423         * they will be handled correctly.
424         */
425        if (lexicalSubStateIndex != 1) {
426            strLexicalState += "|";
427        }
428        strLexicalState += remoteCommand.getArgument(lexicalSubStateIndex);
429    }
430
431    // Translate lexical to numerical substate
432    if (!pCriterionType->getNumericalValue(strLexicalState, iNumericalState)) {
433
434        strResult = "Unable to find lexical state \"" + strLexicalState + "\" in criteria " +
435                    strCriterionName;
436
437        return false;
438    }
439
440    // Set criterion new state
441    pCriterion->setCriterionState(iNumericalState);
442
443    return true;
444}
445