/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
#include <stdlib.h>
#include <algorithm>
#include "Log.h"
#include "StringUtil.h"
#include "task/TaskSequential.h"
#include "task/TaskCase.h"
#include "task/TaskAsync.h"
TaskSequential::TaskSequential()
: TaskGeneric(TaskGeneric::ETaskSequential),
mRepeatCount(1),
mRepeatIndex(-1)
{
}
TaskSequential::~TaskSequential()
{
}
TaskGeneric::ExecutionResult TaskSequential::run()
{
mRepeatIndex = -1;
bool storeIndex = (mIndexName.length() == 0 ? false: true);
if (storeIndex && !getTestCase()->registerIndex(mIndexName, mRepeatIndex)) {
if (!getTestCase()->updateIndex(mIndexName, mRepeatIndex)) {
LOGE("register/update of index %s failed", mIndexName.string());
return TaskGeneric::EResultError;
}
}
TaskGeneric::ExecutionResult firstError(TaskGeneric::EResultOK);
for (mRepeatIndex = 0; mRepeatIndex < mRepeatCount; mRepeatIndex++) {
LOGI(" TaskSequential index %s loop %d-th", mIndexName.string(), mRepeatIndex);
if (storeIndex && !getTestCase()->updateIndex(mIndexName, mRepeatIndex)) {
return TaskGeneric::EResultError;
}
std::list<TaskGeneric*>::iterator i = getChildren().begin();
std::list<TaskGeneric*>::iterator end = getChildren().end();
for (; i != end; i++) {
TaskGeneric* child = *i;
TaskGeneric::ExecutionResult result = child->run();
if ((result != TaskGeneric::EResultOK) && (firstError == TaskGeneric::EResultOK)) {
firstError = result;
break;
}
}
TaskGeneric::ExecutionResult result = runAsyncTasksQueued();
if ((result != TaskGeneric::EResultOK) && (firstError == TaskGeneric::EResultOK)) {
firstError = result;
}
switch (firstError) {
case TaskGeneric::EResultOK:
case TaskGeneric::EResultContinue:
// continue at the last index should be treated as OK
firstError = TaskGeneric::EResultOK;
break; // continue for loop
case TaskGeneric:: EResultBreakOneLoop:
return TaskGeneric::EResultOK;
case TaskGeneric::EResultError:
case TaskGeneric::EResultFail:
case TaskGeneric::EResultPass:
mRepeatIndex = mRepeatCount; //exit for loop
break;
}
}
// update to the loop exit value
if (storeIndex && !getTestCase()->updateIndex(mIndexName, mRepeatIndex)) {
return TaskGeneric::EResultError;
}
return firstError;
}
bool TaskSequential::queueAsyncTask(TaskAsync* task)
{
std::list<TaskAsync*>::iterator it;
it = std::find(mAsyncTasks.begin(), mAsyncTasks.end(), task);
if (it != mAsyncTasks.end()) { // already queued
return true;
}
mAsyncTasks.push_back(task);
return true;
}
TaskGeneric::ExecutionResult TaskSequential::runAsyncTasksQueued()
{
std::list<TaskAsync*>::iterator i = mAsyncTasks.begin();
std::list<TaskAsync*>::iterator end = mAsyncTasks.end();
TaskGeneric::ExecutionResult firstError(TaskGeneric::EResultOK);
for (; i != end; i++) {
TaskAsync* child = *i;
TaskGeneric::ExecutionResult result = child->complete();
if ((result != TaskGeneric::EResultOK) && (firstError == TaskGeneric::EResultOK)) {
firstError = result;
}
}
mAsyncTasks.clear();
return firstError;
}
bool TaskSequential::parseAttribute(const android::String8& name, const android::String8& value)
{
if (StringUtil::compare(name, "repeat") == 0) {
mRepeatCount = atoi(value.string());
if (mRepeatCount <= 0) {
LOGE("TaskSequential::parseAttribute invalid value %s for key %s",
value.string(), name.string());
return false;
}
return true;
} else if (StringUtil::compare(name, "index") == 0) {
mIndexName.append(value);
LOGD("TaskSequential::parseAttribute index %s", mIndexName.string());
return true;
} else {
return false;
}
}