- Completed test-history. I still have some doubts about some points, but I think the current implementation is already a pretty intensive test...
git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@779 3ecf2c5c-341e-0410-92b4-d18e462d057c
This commit is contained in:
parent
14b5b66b3c
commit
a92b542081
|
@ -58,6 +58,12 @@ DynamicProcess::get_threads()
|
|||
return vector<Thread*>(_dynamic_threads.begin(), _dynamic_threads.end());
|
||||
}
|
||||
|
||||
std::vector<const Thread*>
|
||||
DynamicProcess::get_threads() const
|
||||
{
|
||||
return vector<const Thread*>(_dynamic_threads.begin(), _dynamic_threads.end());
|
||||
}
|
||||
|
||||
Schedulable::state
|
||||
DynamicProcess::get_state() const
|
||||
{
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace sgpem
|
|||
virtual ~DynamicProcess();
|
||||
|
||||
std::vector<Thread*> get_threads();
|
||||
std::vector<const Thread*> get_threads() const;
|
||||
|
||||
state get_state() const;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace sgpem
|
|||
virtual ~Process();
|
||||
|
||||
virtual std::vector<Thread*> get_threads() = 0;
|
||||
virtual std::vector<const Thread*> get_threads() const = 0;
|
||||
virtual void serialize(SerializeVisitor& translator) const = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ class DummyObserver : public HistoryObserver
|
|||
{
|
||||
cout << "Observer.update() : " << ++_i << endl;
|
||||
}
|
||||
private:
|
||||
unsigned int _i;
|
||||
};
|
||||
|
||||
|
@ -87,10 +86,55 @@ struct SubRequestCreationData
|
|||
Request* request;
|
||||
History::resource_key_t resource_key;
|
||||
time_t duration;
|
||||
size_t places;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
DynamicThread&
|
||||
find_thread(ConcreteEnvironment& env, Thread& _thread)
|
||||
{
|
||||
DynamicThread& thread = (DynamicThread&)_thread;
|
||||
Environment::Processes& processes = env.get_processes();
|
||||
|
||||
// please forgive me, I'm sick of using iterators...
|
||||
for(unsigned int i = 0; i < processes.size(); ++i)
|
||||
{
|
||||
Process& p = *processes[i];
|
||||
vector<Thread*> threads = p.get_threads();
|
||||
|
||||
for(unsigned int j = 0; j < threads.size(); ++j)
|
||||
{
|
||||
DynamicThread& t = (DynamicThread&)*threads[j];
|
||||
if(t == thread)
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
const DynamicThread&
|
||||
find_thread(const ConcreteEnvironment& env, const Thread& _thread)
|
||||
{
|
||||
const DynamicThread& thread = (DynamicThread&)_thread;
|
||||
const Environment::Processes& processes = env.get_processes();
|
||||
|
||||
// please forgive me, I'm sick of using iterators...
|
||||
for(unsigned int i = 0; i < processes.size(); ++i)
|
||||
{
|
||||
const Process& p = *processes[i];
|
||||
vector<const Thread*> threads = p.get_threads();
|
||||
|
||||
for(unsigned int j = 0; j < threads.size(); ++j)
|
||||
{
|
||||
const DynamicThread& t = (const DynamicThread&)*threads[j];
|
||||
if(t == thread)
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
|
@ -111,23 +155,14 @@ main(int argc, char** argv)
|
|||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
Environment& environment = h.get_last_environment();
|
||||
const ConcreteEnvironment& environment = h.get_last_environment();
|
||||
|
||||
info << "Obtained the only contained environment\n";
|
||||
|
||||
test << "Checking if it is a ConcreteEnvironment... ";
|
||||
|
||||
if(typeid(environment) == typeid(ConcreteEnvironment))
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
test << "Checking if the environment is empty... ";
|
||||
|
||||
if(environment.get_processes().size() == 0 &&
|
||||
environment.get_resources().size() == 0 &&
|
||||
environment.get_request_queue().size() == 0 &&
|
||||
environment.get_sorted_queue().size() == 0)
|
||||
test << "PASS";
|
||||
else
|
||||
|
@ -140,23 +175,23 @@ main(int argc, char** argv)
|
|||
|
||||
h.attach(observer);
|
||||
|
||||
info << "Attached to the history\n;
|
||||
info << "Attached to the history\n";
|
||||
|
||||
ProcessCreationData processes[2] =
|
||||
const ProcessCreationData processes[2] =
|
||||
{
|
||||
{ "p1", 0, 3 },
|
||||
{ "p2", 3, 1 }
|
||||
};
|
||||
|
||||
Process& p1 = h.add_process(processes[0].name,
|
||||
processes[0].arrival_time,
|
||||
processes[0].base_priority);
|
||||
DynamicProcess& p1 = h.add_process(processes[0].name,
|
||||
processes[0].arrival_time,
|
||||
processes[0].base_priority);
|
||||
|
||||
Process& p2 = h.add_process(processes[1].name,
|
||||
processes[1].arrival_time,
|
||||
processes[1].base_priority);
|
||||
DynamicProcess& p2 = h.add_process(processes[1].name,
|
||||
processes[1].arrival_time,
|
||||
processes[1].base_priority);
|
||||
|
||||
ThreadCreationData threads[4] =
|
||||
const ThreadCreationData threads[4] =
|
||||
{
|
||||
{ "p2_1", &p2, 3, 0, 0 },
|
||||
{ "p1_1", &p1, 2, 0, 2 },
|
||||
|
@ -164,89 +199,343 @@ main(int argc, char** argv)
|
|||
{ "p2_2", &p2, 5, 3, 1 }
|
||||
};
|
||||
|
||||
Thread& p2_1 = h.add_thread(threads[0].name,
|
||||
*threads[0].parent,
|
||||
threads[0].cpu_time,
|
||||
threads[0].arrival_time,
|
||||
threads[0].base_priority);
|
||||
DynamicThread& p2_1 = h.add_thread(threads[0].name,
|
||||
*threads[0].parent,
|
||||
threads[0].cpu_time,
|
||||
threads[0].arrival_time,
|
||||
threads[0].base_priority);
|
||||
|
||||
Thread& p1_1 = h.add_thread(threads[1].name,
|
||||
*threads[1].parent,
|
||||
threads[1].cpu_time,
|
||||
threads[1].arrival_time,
|
||||
threads[1].base_priority);
|
||||
DynamicThread& p1_1 = h.add_thread(threads[1].name,
|
||||
*threads[1].parent,
|
||||
threads[1].cpu_time,
|
||||
threads[1].arrival_time,
|
||||
threads[1].base_priority);
|
||||
|
||||
Thread& p1_2 = h.add_thread(threads[2].name,
|
||||
*threads[2].parent,
|
||||
threads[2].cpu_time,
|
||||
threads[2].arrival_time,
|
||||
threads[2].base_priority);
|
||||
DynamicThread& p1_2 = h.add_thread(threads[2].name,
|
||||
*threads[2].parent,
|
||||
threads[2].cpu_time,
|
||||
threads[2].arrival_time,
|
||||
threads[2].base_priority);
|
||||
|
||||
Thread& p2_2 = h.add_thread(threads[3].name,
|
||||
*threads[3].parent,
|
||||
threads[3].cpu_time,
|
||||
threads[3].arrival_time,
|
||||
threads[3].base_priority);
|
||||
DynamicThread& p2_2 = h.add_thread(threads[3].name,
|
||||
*threads[3].parent,
|
||||
threads[3].cpu_time,
|
||||
threads[3].arrival_time,
|
||||
threads[3].base_priority);
|
||||
|
||||
ResourceCreationData resources[2] =
|
||||
const ResourceCreationData resources[2] =
|
||||
{
|
||||
{ "res1", true, 2, 0 },
|
||||
{ "res2", false, 1, 0 }
|
||||
};
|
||||
|
||||
History::ResourcePair res1 = h.add_resource(resources[0].name,
|
||||
resources[0].preemptable,
|
||||
resources[0].places,
|
||||
resources[0].availability);
|
||||
const History::ResourcePair res1 = h.add_resource(resources[0].name,
|
||||
resources[0].preemptable,
|
||||
resources[0].places,
|
||||
resources[0].availability);
|
||||
|
||||
History::ResourcePair res2 = h.add_resource(resources[1].name,
|
||||
resources[1].preemptable,
|
||||
resources[1].places,
|
||||
resources[1].availability);
|
||||
const History::ResourcePair res2 = h.add_resource(resources[1].name,
|
||||
resources[1].preemptable,
|
||||
resources[1].places,
|
||||
resources[1].availability);
|
||||
|
||||
RequestCreationData requests[2] =
|
||||
const RequestCreationData requests[2] =
|
||||
{
|
||||
{ &p1_2, 0 },
|
||||
{ &p2_1, 1 }
|
||||
};
|
||||
|
||||
Request& req1 = h.add_request(*requests[0].owner, requests[0].instant);
|
||||
DynamicRequest& req1 = h.add_request(*requests[0].owner, requests[0].instant);
|
||||
|
||||
Request& req2 = h.add_request(*requests[1].owner, requests[1].instant);
|
||||
DynamicRequest& req2 = h.add_request(*requests[1].owner, requests[1].instant);
|
||||
|
||||
SubRequestCreationData subrequests[3] =
|
||||
const SubRequestCreationData subrequests[3] =
|
||||
{
|
||||
{ &req1, res1.first, 1, 1 },
|
||||
{ &req2, res2.first, 2, 1 },
|
||||
{ &req2, res1.first, 1, 2 }
|
||||
{ &req1, res1.first, 1 },
|
||||
{ &req2, res2.first, 2 },
|
||||
{ &req2, res1.first, 1 }
|
||||
};
|
||||
|
||||
SubRequest& sreq1 = h.add_subrequest(*subrequests[0].request,
|
||||
subrequests[0].resource_key,
|
||||
subrequests[0].duration,
|
||||
subrequests[0].places);
|
||||
const DynamicSubRequest& sreq1 = h.add_subrequest(*subrequests[0].request,
|
||||
subrequests[0].resource_key,
|
||||
subrequests[0].duration);
|
||||
|
||||
SubRequest& sreq2 = h.add_subrequest(*subrequests[1].request,
|
||||
subrequests[1].resource_key,
|
||||
subrequests[1].duration,
|
||||
subrequests[1].places);
|
||||
const DynamicSubRequest& sreq2 = h.add_subrequest(*subrequests[1].request,
|
||||
subrequests[1].resource_key,
|
||||
subrequests[1].duration);
|
||||
|
||||
SubRequest& sreq2 = h.add_subrequest(*subrequests[2].request,
|
||||
subrequests[2].resource_key,
|
||||
subrequests[2].duration,
|
||||
subrequests[2].places);
|
||||
const DynamicSubRequest& sreq3 = h.add_subrequest(*subrequests[2].request,
|
||||
subrequests[2].resource_key,
|
||||
subrequests[2].duration);
|
||||
|
||||
info << "Done adding required data by using the History factory interface\n";
|
||||
|
||||
Environment::Requests res1_queue = environment.get_request_queue(res1.first);
|
||||
Environment::Requests res2_queue = environment.get_request_queue(res2.first);
|
||||
const Environment::Requests res1_queue = environment.get_request_queue(res1.first);
|
||||
const Environment::Requests res2_queue = environment.get_request_queue(res2.first);
|
||||
|
||||
//typedef Environment::Requests::iterator ReqIterator;
|
||||
test << "Checking if the environment contains the correct request queues... ";
|
||||
|
||||
typedef Environment::Requests::const_iterator ReqIterator;
|
||||
|
||||
//for(ReqIterator it = res1_queue.begin(); it !+ res1_queue.end(); ++it)
|
||||
//{
|
||||
|
||||
#warning "Finish me!"
|
||||
if(res1_queue.size() == 2 && res2_queue.size() == 1)
|
||||
{
|
||||
bool res1_req1_match = false;
|
||||
bool res1_req2_match = false;
|
||||
bool res2_req1_match = false;
|
||||
bool bad_match = false;
|
||||
|
||||
for(ReqIterator it = res1_queue.begin(); it != res1_queue.end(); ++it)
|
||||
{
|
||||
if(!res1_req1_match && *it == &req1)
|
||||
res1_req1_match = true;
|
||||
else if(!res1_req2_match && *it == &req2)
|
||||
res1_req2_match == true;
|
||||
else
|
||||
bad_match = true;
|
||||
}
|
||||
|
||||
if(!res2_req1_match && *res2_queue.begin() == &req1)
|
||||
res2_req1_match = true;
|
||||
else
|
||||
bad_match = true;
|
||||
|
||||
if(!bad_match && res1_req1_match && res1_req2_match && res2_req1_match)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
}
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
|
||||
ConcreteEnvironment* environment1 = new ConcreteEnvironment(environment);
|
||||
ConcreteEnvironment* environment2 = new ConcreteEnvironment(environment);
|
||||
ConcreteEnvironment* environment3 = new ConcreteEnvironment(environment);
|
||||
ConcreteEnvironment* environment4 = new ConcreteEnvironment(environment);
|
||||
ConcreteEnvironment* environment5 = new ConcreteEnvironment(environment);
|
||||
|
||||
info << "Created 5 copies of inital environment\n";
|
||||
|
||||
const History::prio_t priorities[5] = { 3, 1, 4, 5, 2 };
|
||||
|
||||
find_thread(*environment1, p1_1).set_priority_push(priorities[0]);
|
||||
find_thread(*environment2, p1_1).set_priority_push(priorities[1]);
|
||||
find_thread(*environment3, p1_1).set_priority_push(priorities[2]);
|
||||
find_thread(*environment4, p1_1).set_priority_push(priorities[3]);
|
||||
find_thread(*environment5, p1_1).set_priority_push(priorities[4]);
|
||||
|
||||
info << "Updated dynamic priority of threads\n";
|
||||
|
||||
h.append_new_environment(environment1);
|
||||
h.append_new_environment(environment2);
|
||||
h.append_new_environment(environment3);
|
||||
h.append_new_environment(environment4);
|
||||
h.append_new_environment(environment5);
|
||||
|
||||
info << "Done appending the environment copies to the history\n";
|
||||
|
||||
test << "Checking if history size is 6... ";
|
||||
|
||||
if(h.get_size() == 6)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
const DynamicThread& t1 = find_thread(h.get_environment_at(1), p1_1);
|
||||
const DynamicThread& t5 = find_thread(h.get_environment_at(5), p1_1);
|
||||
|
||||
test << "Checking if dynamic priority of thread at instant 1 and 5 is different... ";
|
||||
|
||||
if(t1.get_priority_push() != t5.get_priority_push())
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
const DynamicThread& t4 = find_thread(h.get_environment_at(4), p1_1);
|
||||
|
||||
test << "Checking if dynamic priority of thread at instant 4, is different ";
|
||||
test << "from that at instant 1 and 5, and equal to the one expected... ";
|
||||
|
||||
if(t4.get_priority_push() != t1.get_priority_push() &&
|
||||
t4.get_priority_push() != t5.get_priority_push() &&
|
||||
t4.get_priority_push() == priorities[3])
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
test << "Checking whether all subrequests in the last environment ";
|
||||
test << "refer to valid resources... ";
|
||||
|
||||
const ConcreteEnvironment& last_env = h.get_last_environment();
|
||||
const Environment::Processes& le_processes = last_env.get_processes();
|
||||
const Environment::Resources& le_resources = last_env.get_resources();
|
||||
|
||||
bool subreq_pass = true;
|
||||
|
||||
for(unsigned int i = 0; i < le_processes.size(); ++i)
|
||||
{
|
||||
vector<Thread*> threads = le_processes[i]->get_threads();
|
||||
|
||||
for(unsigned int j = 0; j < threads.size(); ++j)
|
||||
{
|
||||
vector<Request*> requests = threads[j]->get_requests();
|
||||
|
||||
for(unsigned int k = 0; k < requests.size(); ++k)
|
||||
{
|
||||
vector<SubRequest*> subrequests = requests[k]->get_subrequests();
|
||||
|
||||
for(unsigned int x = 0; x < subrequests.size(); ++x)
|
||||
{
|
||||
if(le_resources.find(subrequests[x]->get_resource_key()) == le_resources.end())
|
||||
subreq_pass = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(subreq_pass)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
test << "Checking if history throws an exception on accessing a nonexistent environment... ";
|
||||
|
||||
try
|
||||
{
|
||||
h.get_environment_at(6);
|
||||
test << "FAIL";
|
||||
}
|
||||
catch(out_of_range)
|
||||
{
|
||||
test << "PASS";
|
||||
}
|
||||
test << endl;
|
||||
|
||||
ThreadCreationData p1_3_d = { "p1_3", &p1, 3, 4 };
|
||||
|
||||
Thread& p1_3 = h.add_thread(p1_3_d.name,
|
||||
*p1_3_d.parent,
|
||||
p1_3_d.cpu_time,
|
||||
p1_3_d.arrival_time,
|
||||
p1_3_d.base_priority);
|
||||
|
||||
info << "Added new thread, child of process 1\n";
|
||||
|
||||
test << "Checking if history has size 1 after adding a thread... ";
|
||||
|
||||
if(h.get_size() == 1)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
ConcreteEnvironment* environment6 = new ConcreteEnvironment(h.get_last_environment());
|
||||
|
||||
h.append_new_environment(environment6);
|
||||
|
||||
info << "Added a new environment to the history as a clear-cut copy of the last\n";
|
||||
|
||||
h.remove(res1.first);
|
||||
|
||||
info << "Checking if history has size 1 after removing a resource... ";
|
||||
|
||||
if(h.get_size() == 1)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
|
||||
test << "Checking whether objects inside the history are the same as the beginning, ";
|
||||
test << "except for the missing thread and associated requests... ";
|
||||
|
||||
const Environment::Processes& final_processes = h.get_last_environment().get_processes();
|
||||
const Environment::Resources& final_resources = h.get_last_environment().get_resources();
|
||||
|
||||
bool final_p1_match = false;
|
||||
bool final_p2_match = false;
|
||||
bool final_bad_match = false;
|
||||
bool final_sreq2_match = false;
|
||||
|
||||
for(unsigned int i = 0; i < final_processes.size(); ++i)
|
||||
{
|
||||
DynamicProcess& p = (DynamicProcess&)*final_processes[i];
|
||||
|
||||
if(!final_p1_match && p == p1)
|
||||
final_p1_match = true;
|
||||
else if(!final_p2_match && p == p2)
|
||||
final_p2_match = true;
|
||||
else
|
||||
final_bad_match = true;
|
||||
|
||||
vector<DynamicThread*>& threads = p.get_dynamic_threads();
|
||||
|
||||
for(unsigned int j = 0; j < threads.size(); ++j)
|
||||
{
|
||||
vector<DynamicRequest*> requests = threads[j]->get_dynamic_requests();
|
||||
|
||||
for(unsigned int k = 0; k < requests.size(); ++k)
|
||||
{
|
||||
vector<DynamicSubRequest*> subrequests = requests[k]->get_dynamic_subrequests();
|
||||
|
||||
for(unsigned int x = 0; x < subrequests.size(); ++x)
|
||||
{
|
||||
// NOTE this will of course fail if the subrequests which should not be here
|
||||
// are still in the environment
|
||||
if(!final_sreq2_match && *subrequests[i] == sreq2)
|
||||
final_sreq2_match = true;
|
||||
else
|
||||
final_bad_match = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef Environment::Resources::const_iterator ResourceIt;
|
||||
|
||||
if(final_resources.size() == 1)
|
||||
{
|
||||
DynamicResource& r = (DynamicResource&)*(final_resources.begin()->second);
|
||||
if(!(r == *res2.second))
|
||||
final_bad_match = true;
|
||||
}
|
||||
else
|
||||
final_bad_match = true;
|
||||
|
||||
if(!final_bad_match && final_p1_match && final_p2_match && final_sreq2_match)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
|
||||
test << "Checking whether ConcreteHistory throws an exception if we try to use ";
|
||||
test << "a negative index to access an environment... ";
|
||||
|
||||
try
|
||||
{
|
||||
// FIXME This causes a warning because we force a conversion of a negative number
|
||||
// to an unsigned integer. What did the designers wanted to test by doing this?
|
||||
// The compiler?
|
||||
h.get_environment_at(-17);
|
||||
test << "FAIL";
|
||||
}
|
||||
catch(out_of_range)
|
||||
{
|
||||
test << "PASS";
|
||||
}
|
||||
test << endl;
|
||||
|
||||
test << "Internal observer's counter should be 21... ";
|
||||
|
||||
if(observer._i == 21)
|
||||
test << "PASS";
|
||||
else
|
||||
test << "FAIL";
|
||||
test << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue