Home | History | Annotate | Download | only in task
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 #include <sys/types.h>
     18 #include <regex.h>
     19 #include <stdlib.h>
     20 #include <stdio.h>
     21 
     22 #include "Log.h"
     23 #include "audio/RemoteAudio.h"
     24 #include "ClientImpl.h"
     25 #include "Report.h"
     26 #include "Settings.h"
     27 #include "StringUtil.h"
     28 #include "task/TaskCase.h"
     29 
     30 static const android::String8 STR_NAME("name");
     31 static const android::String8 STR_VERSION("version");
     32 static const android::String8 STR_DESCRIPTION("description");
     33 
     34 TaskCase::TaskCase()
     35     : TaskGeneric(TaskGeneric::ETaskCase),
     36       mClient(NULL)
     37 {
     38     const android::String8* list[] = {&STR_NAME, &STR_VERSION, &STR_DESCRIPTION, NULL};
     39     registerSupportedStringAttributes(list);
     40 }
     41 
     42 TaskCase::~TaskCase()
     43 {
     44     delete mClient;
     45 }
     46 
     47 bool TaskCase::getCaseName(android::String8& name) const
     48 {
     49     if (!findStringAttribute(STR_NAME, name)) {
     50         LOGW("TaskCase no name");
     51         return false;
     52     }
     53     return true;
     54 }
     55 
     56 bool TaskCase::addChild(TaskGeneric* child)
     57 {
     58     if ((child->getType() != TaskGeneric::ETaskSetup)
     59             &&  (child->getType() != TaskGeneric::ETaskAction)
     60             &&  (child->getType() != TaskGeneric::ETaskSave)) {
     61         LOGE("TestCase::addChild wrong child type %d", child->getType());
     62         return false;
     63     }
     64     return TaskGeneric::addChild(child);
     65 }
     66 
     67 template <typename T> bool registerGeneric(
     68         typename std::map<android::String8, T>& map,
     69         const android::String8& name, T& data)
     70 {
     71     typename std::map<android::String8, T>::iterator it;
     72     it = map.find(name);
     73     if (it != map.end()) {
     74         LOGV("registerGeneric key %s already registered", name.string());
     75         return false;
     76     }
     77     LOGD("registerGeneric registered key %s", name.string());
     78     map[name] = data;
     79     return true;
     80 }
     81 
     82 template <typename T> bool findGeneric(typename std::map<android::String8, T>& map,
     83         const android::String8& name, T& data)
     84 {
     85     LOGD("findGeneric key %s", name.string());
     86     typename std::map<android::String8, T>::iterator it;
     87     it = map.find(name);
     88     if (it == map.end()) {
     89         return false;
     90     }
     91     data = it->second;
     92     return true;
     93 }
     94 
     95 template <typename T> bool updateGeneric(typename std::map<android::String8, T>& map,
     96         const android::String8& name, T& data)
     97 {
     98     LOGD("updateGeneric key %s", name.string());
     99     typename std::map<android::String8, T>::iterator it;
    100     it = map.find(name);
    101     if (it == map.end()) {
    102         return false;
    103     }
    104     it->second = data;
    105     return true;
    106 }
    107 
    108 // return all the matches for the given regular expression.
    109 // name string and the data itself is copied.
    110 template <typename T> typename std::list<std::pair<android::String8, T> >* findAllGeneric(
    111         typename std::map<android::String8, T>& map, const char* re)
    112 {
    113     regex_t regex;
    114     if (regcomp(&regex, re, REG_EXTENDED | REG_NOSUB) != 0) {
    115         LOGE("regcomp failed");
    116         return NULL;
    117     }
    118     typename std::map<android::String8, T>::iterator it;
    119     typename std::list<std::pair<android::String8, T> >* list = NULL;
    120     for (it = map.begin(); it != map.end(); it++) {
    121         if (regexec(&regex, it->first, 0, NULL, 0) == 0) {
    122             if (list == NULL) { // create only when found
    123                 list = new std::list<std::pair<android::String8, T> >();
    124                 if (list == NULL) {
    125                     regfree(&regex);
    126                     return NULL;
    127                 }
    128             }
    129             typename std::pair<android::String8, T> match(it->first, it->second);
    130             list->push_back(match);
    131         }
    132     }
    133     regfree(&regex);
    134     return list;
    135 }
    136 
    137 
    138 bool TaskCase::registerBuffer(const android::String8& orig, android::sp<Buffer>& buffer)
    139 {
    140     android::String8 translated;
    141     if (!translateVarName(orig, translated)) {
    142         return false;
    143     }
    144     return registerGeneric<android::sp<Buffer> >(mBufferList, translated, buffer);
    145 }
    146 
    147 bool TaskCase::updateBuffer(const android::String8& orig, android::sp<Buffer>& buffer)
    148 {
    149     android::String8 translated;
    150     if (!translateVarName(orig, translated)) {
    151         return false;
    152     }
    153     return updateGeneric<android::sp<Buffer> >(mBufferList, translated, buffer);
    154 }
    155 
    156 android::sp<Buffer> TaskCase::findBuffer(const android::String8& orig)
    157 {
    158     android::String8 translated;
    159     android::sp<Buffer> result;
    160     if (!translateVarName(orig, translated)) {
    161         return result;
    162     }
    163     findGeneric<android::sp<Buffer> >(mBufferList, translated, result);
    164     return result;
    165 }
    166 
    167 std::list<TaskCase::BufferPair>* TaskCase::findAllBuffers(const android::String8& re)
    168 {
    169     android::String8 translated;
    170     if (!translateVarName(re, translated)) {
    171         return NULL;
    172     }
    173     return findAllGeneric<android::sp<Buffer> >(mBufferList, translated.string());
    174 }
    175 
    176 
    177 bool TaskCase::registerValue(const android::String8& orig, Value& val)
    178 {
    179     android::String8 translated;
    180     if (!translateVarName(orig, translated)) {
    181         return false;
    182     }
    183     LOGD("str %x", translated.string());
    184     return registerGeneric<Value>(mValueList, translated, val);
    185 }
    186 
    187 bool TaskCase::updateValue(const android::String8& orig, Value& val)
    188 {
    189     android::String8 translated;
    190     if (!translateVarName(orig, translated)) {
    191         return false;
    192     }
    193     return updateGeneric<Value>(mValueList, translated, val);
    194 }
    195 
    196 bool TaskCase::findValue(const android::String8& orig, Value& val)
    197 {
    198     android::String8 translated;
    199     if (!translateVarName(orig, translated)) {
    200         return false;
    201     }
    202     return findGeneric<Value>(mValueList, translated, val);
    203 }
    204 
    205 std::list<TaskCase::ValuePair>* TaskCase::findAllValues(const android::String8& re)
    206 {
    207     android::String8 translated;
    208     if (!translateVarName(re, translated)) {
    209         return NULL;
    210     }
    211     return findAllGeneric<Value>(mValueList, translated.string());
    212 }
    213 
    214 bool TaskCase::registerIndex(const android::String8& name, int value)
    215 {
    216     return registerGeneric<int>(mIndexList, name, value);
    217 }
    218 
    219 bool TaskCase::updateIndex(const android::String8& name, int value)
    220 {
    221     return updateGeneric<int>(mIndexList, name, value);
    222 }
    223 
    224 bool TaskCase::findIndex(const android::String8& name, int& val)
    225 {
    226     return findGeneric<int>(mIndexList, name, val);
    227 }
    228 
    229 std::list<TaskCase::IndexPair>* TaskCase::findAllIndices(const android::String8& re)
    230 {
    231     android::String8 translated;
    232     if (!translateVarName(re, translated)) {
    233         return NULL;
    234     }
    235     return findAllGeneric<int>(mIndexList, translated.string());
    236 }
    237 
    238 bool TaskCase::translateVarName(const android::String8& orig, android::String8& translated)
    239 {
    240     const char* src = orig.string();
    241     const int nmatch = 2;
    242     regmatch_t pmatch[nmatch];
    243     regex_t re;
    244     size_t strStart = 0;
    245 
    246     if (regcomp(&re, "[a-z0-9_]*[$]([a-z0-9]+)[_]*", REG_EXTENDED) != 0) {
    247         LOGE("regcomp failed");
    248         return false;
    249     }
    250     bool result = false;
    251     size_t matchStart = 0;
    252     size_t matchEnd = 0;
    253     while (regexec(&re, src, nmatch, pmatch, 0) == 0) {
    254         matchStart = strStart + pmatch[1].rm_so;
    255         matchEnd = strStart + pmatch[1].rm_eo;
    256         translated.append(StringUtil::substr(orig, strStart, pmatch[1].rm_so - 1)); //-1 for $
    257         android::String8 indexName;
    258         indexName.append(StringUtil::substr(orig, matchStart, matchEnd - matchStart));
    259         int val;
    260         if (!findIndex(indexName, val)) {
    261             LOGE("TaskCase::translateVarName no index with name %s", indexName.string());
    262             regfree(&re);
    263             return false;
    264         }
    265         translated.appendFormat("%d", val);
    266         LOGD("match found strStart %d, matchStart %d, matchEnd %d, converted str %s",
    267                 strStart, matchStart, matchEnd, translated.string());
    268         src += pmatch[1].rm_eo;
    269         strStart += pmatch[1].rm_eo;
    270     }
    271     if (matchEnd < orig.length()) {
    272         //LOGD("%d %d", matchEnd, orig.length());
    273         translated.append(StringUtil::substr(orig, matchEnd, orig.length() - matchEnd));
    274     }
    275     LOGD("translated str %s to %s", orig.string(), translated.string());
    276     regfree(&re);
    277     return true;
    278 }
    279 
    280 android::sp<RemoteAudio>& TaskCase::getRemoteAudio()
    281 {
    282     if (mClient == NULL) {
    283         mClient = new ClientImpl();
    284         ASSERT(mClient->init(Settings::Instance()->getSetting(Settings::EADB)));
    285     }
    286     return mClient->getAudio();
    287 }
    288 
    289 void TaskCase::releaseRemoteAudio()
    290 {
    291     delete mClient;
    292     mClient = NULL;
    293 }
    294 
    295 void TaskCase::setDetails(const android::String8& details)
    296 {
    297     mDetails = details;
    298 }
    299 
    300 const android::String8& TaskCase::getDetails() const
    301 {
    302     return mDetails;
    303 }
    304 
    305 
    306 TaskGeneric::ExecutionResult TaskCase::run()
    307 {
    308     android::String8 name;
    309     android::String8 version;
    310     //LOGI("str %d, %d", strlen(STR_NAME), strlen(STR_VERSION));
    311     if (!findStringAttribute(STR_NAME, name) || !findStringAttribute(STR_VERSION, version)) {
    312         LOGW("TaskCase::run no name or version information");
    313     }
    314     MSG("== Test case %s version %s started ==", name.string(), version.string());
    315     std::list<TaskGeneric*>::iterator i = getChildren().begin();
    316     std::list<TaskGeneric*>::iterator end = getChildren().end();
    317     TaskGeneric* setup = *i;
    318     i++;
    319     TaskGeneric* action = *i;
    320     i++;
    321     TaskGeneric* save = (i == end)? NULL : *i;
    322     if (save == NULL) {
    323         LOGW("No save stage in test case");
    324     }
    325     bool testPassed = true;
    326     TaskGeneric::ExecutionResult result = setup->run();
    327     TaskGeneric::ExecutionResult resultAction(TaskGeneric::EResultOK);
    328     if (result != TaskGeneric::EResultOK) {
    329         MSG("== setup stage failed %d ==", result);
    330         testPassed = false;
    331     } else {
    332         resultAction = action->run();
    333         if (resultAction != TaskGeneric::EResultPass) {
    334             MSG("== action stage failed %d ==", resultAction);
    335             testPassed = false;
    336         }
    337         // save done even for failure if possible
    338         if (save != NULL) {
    339             result = save->run();
    340         }
    341         if (result != TaskGeneric::EResultOK) {
    342             MSG("== save stage failed %d ==", result);
    343             testPassed = false;
    344         }
    345     }
    346     if (testPassed) {
    347         result = TaskGeneric::EResultPass;
    348         MSG("== Case %s Passed ==", name.string());
    349         Report::Instance()->addCasePassed(this);
    350     } else {
    351         if (resultAction != TaskGeneric::EResultOK) {
    352             result = resultAction;
    353         }
    354         MSG("== Case %s Failed ==", name.string());
    355         Report::Instance()->addCaseFailed(this);
    356     }
    357     // release remote audio for other cases to use
    358     releaseRemoteAudio();
    359     return result;
    360 }
    361 
    362