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)
     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 TaskGeneric::ExecutionResult TaskCase::run()
    296 {
    297     android::String8 name;
    298     android::String8 version;
    299     //LOGI("str %d, %d", strlen(STR_NAME), strlen(STR_VERSION));
    300     if (!findStringAttribute(STR_NAME, name) || !findStringAttribute(STR_VERSION, version)) {
    301         LOGW("TaskCase::run no name or version information");
    302     }
    303     MSG("== Test case %s version %s started ==", name.string(), version.string());
    304     std::list<TaskGeneric*>::iterator i = getChildren().begin();
    305     std::list<TaskGeneric*>::iterator end = getChildren().end();
    306     TaskGeneric* setup = *i;
    307     i++;
    308     TaskGeneric* action = *i;
    309     i++;
    310     TaskGeneric* save = (i == end)? NULL : *i;
    311     if (save == NULL) {
    312         LOGW("No save stage in test case");
    313     }
    314     bool testPassed = true;
    315     TaskGeneric::ExecutionResult result = setup->run();
    316     TaskGeneric::ExecutionResult resultAction(TaskGeneric::EResultOK);
    317     if (result != TaskGeneric::EResultOK) {
    318         MSG("== setup stage failed %d ==", result);
    319         testPassed = false;
    320     } else {
    321         resultAction = action->run();
    322         if (resultAction != TaskGeneric::EResultPass) {
    323             MSG("== action stage failed %d ==", resultAction);
    324             testPassed = false;
    325         }
    326         // save done even for failure if possible
    327         if (save != NULL) {
    328             result = save->run();
    329         }
    330         if (result != TaskGeneric::EResultOK) {
    331             MSG("== save stage failed %d ==", result);
    332             testPassed = false;
    333         }
    334     }
    335     if (testPassed) {
    336         result = TaskGeneric::EResultPass;
    337         MSG("== Case %s Passed ==", name.string());
    338         Report::Instance()->addCasePassed(name);
    339     } else {
    340         if (resultAction != TaskGeneric::EResultOK) {
    341             result = resultAction;
    342         }
    343         MSG("== Case %s Failed ==", name.string());
    344         Report::Instance()->addCaseFailed(name);
    345     }
    346     // release remote audio for other cases to use
    347     releaseRemoteAudio();
    348     return result;
    349 }
    350 
    351 
    352