|
From: <ma...@us...> - 2011-02-02 23:58:04
|
Revision: 1030
http://scstudio.svn.sourceforge.net/scstudio/?rev=1030&view=rev
Author: madzin
Date: 2011-02-02 23:57:58 +0000 (Wed, 02 Feb 2011)
Log Message:
-----------
Add Diff algorithm
Modified Paths:
--------------
trunk/src/membership/CMakeLists.txt
trunk/src/membership/membership_base.h
trunk/tests/CMakeLists.txt
Added Paths:
-----------
trunk/src/membership/diff_impl.cpp
trunk/src/membership/diff_impl.h
trunk/tests/diff/
trunk/tests/diff/CMakeLists.txt
trunk/tests/diff/diff_test.cpp
trunk/tests/diff/flow01.mpr
trunk/tests/diff/flow02_1.mpr
trunk/tests/diff/flow02_2.mpr
trunk/tests/diff/flow02_3.mpr
trunk/tests/diff/spec01.mpr
trunk/tests/diff/spec02.mpr
Modified: trunk/src/membership/CMakeLists.txt
===================================================================
--- trunk/src/membership/CMakeLists.txt 2011-02-02 22:17:59 UTC (rev 1029)
+++ trunk/src/membership/CMakeLists.txt 2011-02-02 23:57:58 UTC (rev 1030)
@@ -8,6 +8,8 @@
membership_additional.cpp
membership_additional.h
membership_base.h
+ diff_impl.h
+ diff_impl.cpp
)
TARGET_LINK_LIBRARIES(scmembership
Added: trunk/src/membership/diff_impl.cpp
===================================================================
--- trunk/src/membership/diff_impl.cpp (rev 0)
+++ trunk/src/membership/diff_impl.cpp 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,487 @@
+/*
+ * scstudio - Sequence Chart Studio
+ * http://scstudio.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (c) 2008 Matus Madzin <go...@ma...>
+ *
+ */
+
+#include "membership/diff_impl.h"
+
+void process_diffrences(BMscPtr dup_flow, const std::map<std::wstring, Difference*>& diff_map);
+
+/**
+ * Find diffrences on instance between flow and specification
+ *
+ * parameters: a - flow
+ * b - specification
+ */
+Difference* instance_diff(InstancePtr a, InstancePtr b);
+
+BMscPtr bmsc_bmsc_diff(BMscPtr specification, BMscPtr flow);
+BMscPtr hmsc_bmsc_diff(HMscPtr specification, BMscPtr flow);
+
+/**
+ * Find msc diffrences between flow and specification
+ *
+ * parameters: a - specification
+ * b - flow
+ */
+MscPtr MembershipAlg::diff(MscPtr specification, BMscPtr flow)
+{
+ BMscPtr bmsc = boost::dynamic_pointer_cast<BMsc > (specification);
+
+ if (bmsc == NULL)
+ {
+ HMscPtr hmsc = boost::dynamic_pointer_cast<HMsc > (specification);
+
+ return hmsc_bmsc_diff(hmsc, flow);
+ }
+ else
+ return bmsc_bmsc_diff(bmsc, flow);
+}
+
+Difference* instance_diff(InstancePtr a, InstancePtr b)
+{
+ std::vector<StrictEventPtr> a_ordering;
+ std::vector<StrictEventPtr> b_ordering;
+ int row = 0;
+ int col = 0;
+
+ EventAreaPtr a_area = a->get_first();
+ EventAreaPtr b_area = b->get_first();
+
+ StrictOrderAreaPtr a_soa = boost::dynamic_pointer_cast<StrictOrderArea > (a_area);
+ StrictOrderAreaPtr b_soa = boost::dynamic_pointer_cast<StrictOrderArea > (b_area);
+
+ StrictEventPtr event_a = a_soa->get_first();
+ StrictEventPtr event_b = b_soa->get_first();
+
+ StrictEventPtr start_a, start_b;
+
+ if (event_a != NULL)
+ start_a = event_a;
+ if (event_b != NULL)
+ start_b = event_b;
+
+ //TODO check what is in context, maybe it is necessary to replace it.
+ MembershipContext* c = new MembershipContext();
+
+ while (event_a != NULL || event_b != NULL)
+ {
+ if (!compare_events(c, event_a.get(), event_b.get()))
+ break;
+
+ row++;
+ event_a = event_a->get_successor();
+ event_b = event_b->get_successor();
+ }
+
+ int lower, upper;
+
+ if (event_a == NULL)
+ lower = 1;
+ else
+ lower = -1;
+
+ if (event_b == NULL)
+ upper = -1;
+ else
+ upper = 1;
+
+ if (lower > upper)
+ //instances are same
+ return NULL;
+
+ int d; //current edit distance
+ std::map<int, Distance*> last_d;
+ std::map<int, Difference*> script;
+
+ last_d[0] = new Distance(event_a, row);
+ script[0] = NULL;
+ col = row;
+
+ for (d = 1; d < 100; d++)
+ {
+ for (int k = lower; k <= upper; k += 2)
+ {
+ Difference* diff = new Difference();
+ std::map<int, Distance*>::iterator down, up;
+ down = last_d.find(k - 1);
+ up = last_d.find(k + 1);
+ bool result = false;
+
+ if (down == last_d.end() || (up != last_d.end() && up->second->getLine() >= down->second->getLine()))
+ result = true;
+
+ StrictEventPtr old_a;
+ if ((k == -d || k != d) && result)
+ {
+ // moving down from the last d-1 on diagonal k+1
+ // puts you farther along diagonal k than does
+ // moving right from the last d-1 on diagonal k-1
+ if (up != last_d.end())
+ {
+ old_a = up->second->getEvent();
+ event_a = up->second->getEvent()->get_successor();
+ row = up->second->getLine() + 1;
+ }
+ else
+ {
+ row = 1;
+
+ if (start_a != NULL)
+ event_a = start_a->get_successor();
+ else
+ {
+ //TODO cover the error message
+ throw std::runtime_error("Error: unexpected behaviour");
+ }
+ old_a = event_a;
+ }
+
+ if (script.find(k + 1) != script.end())
+ diff->setPrevious(script[k + 1]);
+
+ diff->setOperation(DELETE);
+ diff->setLocation(old_a);
+ diff->setMessage(old_a->get_message(), old_a->is_send());
+ }
+ else
+ {
+ // move right from the last d-1 on diagonal k-1
+ if (down != last_d.end())
+ {
+ old_a = down->second->getEvent();
+ event_a = down->second->getEvent();
+ row = down->second->getLine();
+ }
+ else
+ {
+ row = 1;
+
+ if (start_a != NULL)
+ event_a = start_a->get_successor();
+ else
+ {
+ //TODO cover the error message
+ throw std::runtime_error("Error: unexpected behaviour");
+ }
+ old_a = event_a;
+ }
+
+ if (script.find(k - 1) != script.end())
+ diff->setPrevious(script[k - 1]);
+
+ diff->setOperation(INSERT);
+
+ //TODO nemozem takto prechadzat eventy od zaciatku
+ StrictEventPtr s = start_b;
+ for (int i = 0; i < (row + k - 1); i++)
+ {
+ s = s->get_successor();
+ }
+
+ //TODO nemozem takto prechadzat eventy od zaciatku
+ StrictEventPtr r = start_a;
+ for (int i = 0; i < row - 1; i++)
+ {
+ r = r->get_successor();
+ }
+ if(row - 1 <= 0)
+ r = NULL;
+
+ diff->setLocation(r);
+ diff->setMessage(s->get_message(), s->is_send());
+ }
+
+ int old_col = col;
+ col = row + k;
+ int rest = col - old_col;
+
+ if (rest > 0)
+ {
+ for (int i = 0; i < rest; i++)
+ {
+ if (event_b != NULL)
+ event_b = event_b->get_successor();
+ }
+ }
+ else
+ {
+ for (int i = rest; i < 0; i++)
+ {
+ if (event_b != NULL)
+ event_b = event_b->get_predecessor();
+ else
+ event_b = b_soa->get_last();
+ }
+ }
+
+ diff->setLine1(row);
+ diff->setLine2(col);
+ script[k] = diff;
+
+
+ while (event_a != NULL && event_b != NULL && compare_events(c, event_a.get(), event_b.get()))
+ {
+ event_a = event_a->get_successor();
+ event_b = event_b->get_successor();
+ row++;
+ col++;
+ }
+
+ last_d[k] = new Distance(event_a, row);
+
+ if (event_a == NULL && event_b == NULL)
+ // hit southeast corner, have the answer
+ return script[k];
+
+ if (event_a == NULL)
+ // hit the last row, don't look to the left
+ lower = k + 2;
+
+ if (event_b == NULL)
+ // hit the last column, don't look to the right
+ upper = k - 2;
+ }
+
+ --lower;
+ ++upper;
+ }
+
+ //TODO pridane lebo warning, overit ci sa niekedy mozme dostat do tohto miesta v korektnom behu
+ throw std::runtime_error("Error: I don't know");
+}
+
+BMscPtr bmsc_bmsc_diff(BMscPtr specification, BMscPtr flow)
+{
+ BMscDuplicator duplicator;
+ BMscPtr dup_flow;
+
+ dup_flow = duplicator.duplicate(flow);
+
+ InstancePtrList spec_inst = specification->get_instances();
+ InstancePtrList flow_inst = dup_flow->get_instances();
+
+ std::map<std::wstring, Difference*> diff_map;
+
+ InstancePtrList::iterator spec_it;
+ InstancePtrList::iterator flow_it;
+
+ for (spec_it = spec_inst.begin(); spec_it != spec_inst.end(); spec_it++)
+ {
+ for (flow_it = flow_inst.begin(); flow_it != flow_inst.end(); flow_it++)
+ {
+ if ((*spec_it)->get_label() == (*flow_it)->get_label())
+ {
+ Difference* diff = instance_diff(*flow_it, *spec_it);
+
+ if(diff != NULL)
+ diff_map.insert(std::make_pair((*flow_it)->get_label(), diff));
+ }
+ }
+ }
+
+ if(!diff_map.empty())
+ {
+ process_diffrences(dup_flow, diff_map);
+ return dup_flow;
+ }
+ else
+ return NULL;
+}
+
+BMscPtr hmsc_bmsc_diff(HMscPtr specification, BMscPtr flow)
+{
+ std::cerr << "Error: this feature is not supported yet" << std::endl;
+ return NULL;
+}
+
+StrictOrderAreaPtr get_proper_area(BMscPtr flow, std::wstring inst_name)
+{
+ InstancePtrList instances = flow->get_instances();
+ InstancePtrList::iterator instances_it;
+
+ for(instances_it = instances.begin(); instances_it != instances.end(); instances_it++)
+ {
+ if((*instances_it)->get_label() == inst_name)
+ break;
+ }
+
+//TODO ak je to sprava na instanciu ktora sa vo flow nenachadza tak bude splnena podmienka a error to nie je
+ if(instances_it == instances.end())
+ throw std::runtime_error("Error: unexpected behaviour");
+
+ EventAreaPtr e_a = (*instances_it)->get_first();
+
+//TODO
+// if(e_a == NULL)
+
+ StrictOrderAreaPtr s_e_a = boost::dynamic_pointer_cast<StrictOrderArea> (e_a);
+
+ if(s_e_a == NULL)
+ throw std::runtime_error("Error: unexpected behaviour, check whether flow MSC does not contain coregion");
+
+ return s_e_a;
+}
+
+void process_diffrences(BMscPtr dup_flow, const std::map<std::wstring, Difference*>& diff_map)
+{
+ std::map<std::wstring, Difference*>::const_iterator it;
+ std::map<std::wstring, std::list<Difference*> > insert_map;
+ Difference* diff;
+
+ for (it = diff_map.begin(); it != diff_map.end(); it++)
+ {
+ std::list<Difference*> insert_list;
+ diff = it->second;
+
+ if (diff == NULL)
+ continue;
+
+ while (diff != NULL)
+ {
+ if (diff->getOperation() == DELETE)
+ {
+ diff->getLocation()->set_marked(REMOVED);
+ diff->getLocation()->get_message()->set_marked(REMOVED);
+ }
+ else
+ insert_list.push_back(diff);
+
+ diff = diff->getPrevious();
+ }
+
+ insert_map.insert(std::make_pair(it->first, insert_list));
+ }
+
+ std::set<Difference*> recently_processed;
+ std::map<std::wstring, std::list<Difference*> >::iterator ins_map_it;
+ for (ins_map_it = insert_map.begin(); ins_map_it != insert_map.end(); ins_map_it++)
+ {
+ std::list<Difference*> insert_list = ins_map_it->second;
+ std::list<Difference*>::iterator ins_list_it;
+
+ for (ins_list_it = insert_list.begin(); ins_list_it != insert_list.end(); ins_list_it++)
+ {
+ if(recently_processed.find(*ins_list_it) != recently_processed.end())
+ continue;
+
+ MscMessagePtr message = (*ins_list_it)->getMessage();
+ CompleteMessagePtr com_msg = boost::dynamic_pointer_cast<CompleteMessage> (message);
+
+ //In case the message is incommplete, create new event, add it to the proper ordering
+ if (com_msg == NULL)
+ {
+ //TODO refactoring, get it to the separated function
+ IncompleteMessagePtr in_msg = boost::dynamic_pointer_cast<IncompleteMessage > (message);
+ StrictEventPtr new_e = new StrictEvent();
+
+ IncompleteMessagePtr new_msg = new IncompleteMessage(
+ in_msg->is_lost() ? LOST : FOUND,
+ in_msg->get_label(),
+ in_msg->get_instance_label());
+
+ new_msg->glue_event(new_e);
+
+ if((*ins_list_it)->getLocation() != NULL)
+ (*ins_list_it)->getLocation()->set_successor(new_e);
+ else
+ {
+ StrictOrderAreaPtr s_e_a = get_proper_area(dup_flow, ins_map_it->first);
+
+ new_e->set_successor(s_e_a->get_first());
+ s_e_a->set_first(new_e);
+ }
+
+ continue;
+ }
+
+ std::wstring match_inst;
+
+ if ((*ins_list_it)->getDirection() == SEND)
+ match_inst = com_msg->get_receiver()->get_label();
+ else
+ match_inst = com_msg->get_sender()->get_label();
+
+ std::list<Difference*> match_insert_list;
+
+ match_insert_list = insert_map.find(match_inst)->second;
+
+ std::list<Difference*>::iterator match_ins_list_it;
+ Difference* match_diff;
+
+ for (match_ins_list_it = match_insert_list.begin();
+ match_ins_list_it != match_insert_list.end();
+ match_ins_list_it++)
+ {
+ if ((*match_ins_list_it)->getMessage() == message)
+ {
+ match_diff = *match_ins_list_it;
+ break;
+ }
+ }
+
+ recently_processed.insert(match_diff);
+
+ StrictEventPtr predecessor1 = (*ins_list_it)->getLocation();
+ StrictEventPtr predecessor2 = match_diff->getLocation();
+
+ StrictEventPtr new_e1 = new StrictEvent();
+ StrictEventPtr new_e2 = new StrictEvent();
+
+
+ StrictOrderAreaPtr strict_e_a1, strict_e_a2;
+
+ if(predecessor1 == NULL)
+ strict_e_a1 = get_proper_area(dup_flow, ins_map_it->first);
+ else
+ strict_e_a1 = predecessor1->get_area();
+
+ if(predecessor2 == NULL)
+ strict_e_a2 = get_proper_area(dup_flow, ins_map_it->first);
+ else
+ strict_e_a2 = predecessor2->get_area();
+
+ new_e1->set_area(strict_e_a1.get());
+ new_e2->set_area(strict_e_a2.get());
+
+ new_e1->set_marked(ADDED);
+ new_e2->set_marked(ADDED);
+
+ CompleteMessagePtr new_msg = new CompleteMessage(message->get_label());
+ new_msg->set_marked(ADDED);
+
+ if ((*ins_list_it)->getDirection() == SEND)
+ new_msg->glue_events(new_e1, new_e2);
+ else
+ new_msg->glue_events(new_e2, new_e1);
+
+ if(predecessor1 == NULL)
+ {
+ new_e1->set_successor(strict_e_a1->get_first());
+ strict_e_a1->set_first(new_e1);
+ }
+ else
+ predecessor1->set_successor(new_e1);
+
+ if(predecessor2 == NULL)
+ {
+ new_e2->set_successor(strict_e_a2->get_first());
+ strict_e_a2->set_first(new_e2);
+ }
+ else
+ predecessor2->set_successor(new_e2);
+ }
+ }
+}
Added: trunk/src/membership/diff_impl.h
===================================================================
--- trunk/src/membership/diff_impl.h (rev 0)
+++ trunk/src/membership/diff_impl.h 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,156 @@
+/*
+ * scstudio - Sequence Chart Studio
+ * http://scstudio.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (c) 2008 Matus Madzin <go...@ma...>
+ *
+ */
+
+#ifndef __DIFF_IMPL__
+#define __DIFF_IMPL__
+
+#include "membership_additional.h"
+
+enum Operation {INSERT, DELETE};
+enum Direction {SEND, RECEIVE};
+
+class Distance
+{
+private:
+ StrictEventPtr event;
+ int line;
+
+public:
+ Distance(StrictEventPtr e, int l)
+ {
+ event = e;
+ line = l;
+ }
+
+ StrictEventPtr getEvent()
+ {
+ return event;
+ }
+
+ void setEvent(StrictEventPtr e)
+ {
+ event = e;
+ }
+
+ int getLine()
+ {
+ return line;
+ }
+
+ void setLine(int l)
+ {
+ line = l;
+ }
+};
+
+class Difference
+{
+private:
+ Difference* previous;
+ StrictEventPtr location;
+ MscMessagePtr message;
+ enum Direction dir;
+ enum Operation op;
+ int line1;
+ int line2;
+
+public:
+ Difference()
+ {
+ previous = NULL;
+ }
+
+ void setPrevious(Difference* diff)
+ {
+ previous = diff;
+ }
+
+ Difference* getPrevious()
+ {
+ return previous;
+ }
+
+ void setOperation(enum Operation operation)
+ {
+ op = operation;
+ }
+
+ enum Operation getOperation()
+ {
+ return op;
+ }
+
+ void setLine1(int row)
+ {
+ line1 = row;
+ }
+
+ int getLine1()
+ {
+ return line1;
+ }
+
+ void setLine2(int col)
+ {
+ line2 = col;
+ }
+
+ int getLine2()
+ {
+ return line2;
+ }
+
+ void setLocation(StrictEventPtr e)
+ {
+ location = e;
+ }
+
+ StrictEventPtr getLocation()
+ {
+ return location;
+ }
+
+ /**
+ * parameter m - message connected with the event
+ * (DELETE - message of deleted event)
+ * (INSERT - message which is supposed to add)
+ * send - bool whether the event is supposed to be send.
+ */
+ void setMessage(MscMessagePtr m, bool send)
+ {
+ message = m;
+
+ if(send)
+ dir = SEND;
+ else
+ dir = RECEIVE;
+ }
+
+ MscMessagePtr getMessage()
+ {
+ return message;
+ }
+
+ enum Direction getDirection()
+ {
+ return dir;
+ }
+};
+
+void diff(InstancePtr first, InstancePtr second);
+
+#endif
Modified: trunk/src/membership/membership_base.h
===================================================================
--- trunk/src/membership/membership_base.h 2011-02-02 22:17:59 UTC (rev 1029)
+++ trunk/src/membership/membership_base.h 2011-02-02 23:57:58 UTC (rev 1030)
@@ -800,6 +800,9 @@
//! Finds the bmsc flow in hmsc specification
virtual MscPtr find(MscPtr hmsc, MscPtr bmsc);
+
+ //! Make diff between specification and flow
+ virtual MscPtr diff(MscPtr specification, BMscPtr flow);
//! Finds each bmsc flow from the vector in hmsc specification
virtual MscPtr find(MscPtr hmsc, std::vector<MscPtr>& bmscs);
Modified: trunk/tests/CMakeLists.txt
===================================================================
--- trunk/tests/CMakeLists.txt 2011-02-02 22:17:59 UTC (rev 1029)
+++ trunk/tests/CMakeLists.txt 2011-02-02 23:57:58 UTC (rev 1030)
@@ -113,6 +113,7 @@
ADD_SUBDIRECTORY(z120_test)
ADD_SUBDIRECTORY(membership)
+ADD_SUBDIRECTORY(diff)
ADD_SUBDIRECTORY(montecarlo)
ADD_EXECUTABLE(checker_test
Added: trunk/tests/diff/CMakeLists.txt
===================================================================
--- trunk/tests/diff/CMakeLists.txt (rev 0)
+++ trunk/tests/diff/CMakeLists.txt 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,23 @@
+ADD_EXECUTABLE(diff_test
+ diff_test.cpp
+)
+
+TARGET_LINK_LIBRARIES(diff_test
+ scmembership
+ scpseudocode
+ scmsc
+ scZ120
+)
+
+#ADD_MEMBERSHIP_TEST(sctime "Correct Time Constraint Syntax" connector_correct0.mpr 1)
+
+#ADD_MEMBERSHIP_TEST(test_hmsc01 test_bmsc01 1)
+
+GET_TARGET_PROPERTY(DIFF_TEST_EXECUTABLE diff_test LOCATION)
+# Replace the "$(IntDir)", "$(OutDir)", or "$(CONFIGURATION)"
+# depending on the generator being used with the test-time variable.
+STRING(REGEX REPLACE "\\$\\(.*\\)" "\${CTEST_CONFIGURATION_TYPE}"
+ DIFF_TEST_EXECUTABLE "${DIFF_TEST_EXECUTABLE}")
+
+ADD_TEST(diff_test-01 ${DIFF_TEST_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/spec01.mpr ${CMAKE_CURRENT_SOURCE_DIR}/flow01.mpr 1)
+
Added: trunk/tests/diff/diff_test.cpp
===================================================================
--- trunk/tests/diff/diff_test.cpp (rev 0)
+++ trunk/tests/diff/diff_test.cpp 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,142 @@
+/*
+ * scstudio - Sequence Chart Studio
+ * http://scstudio.sourceforge.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (c) 2009 Matus Madzin <go...@ma...>
+ *
+ */
+
+#include <string.h>
+#include <iostream>
+
+#include "data/Z120/z120.h"
+#include "membership/membership_alg.h"
+
+char* extract_filename(char* filename)
+{
+ char *last_name = filename;
+ char *last_dot = NULL;
+
+ for(char *pos = filename; *pos != '\0'; pos++)
+ {
+ if(*pos == '.')
+ last_dot = pos;
+ else if(*pos == '\\' || *pos == '/')
+ last_name = pos+1;
+ }
+
+ if(last_dot != NULL)
+ *last_dot = '\0'; // strip the extension
+
+ return last_name;
+}
+
+int main(int argc, char** argv)
+{
+ if(argc < 4)
+ {
+ std::cerr << "Usage: " << argv[0] << " <filename> <filename> <satisfied>" << std::endl;
+ return 1;
+ }
+
+ std::vector<std::wstring> focused_instances;
+
+ for(int i = 4; i < argc; i++)
+ {
+ std::string s = argv[i];
+ std::wstring temp(s.length(),L' ');
+ std::copy(s.begin(), s.end(), temp.begin());
+
+ focused_instances.push_back(temp);
+ }
+
+ Z120 z120;
+
+ StreamReportPrinter printer(std::wcerr);
+ z120.set_printer(&printer);
+
+ int errors = 0;
+
+ char *endptr;
+ int satisfied = strtol(argv[3], &endptr, 10);
+ if(*argv[3] == '\0' || *endptr != '\0')
+ {
+ std::cerr << "ERROR: Not a boolean value: " << argv[3] << std::endl;
+ return 1;
+ }
+
+ std::vector<MscPtr> msc;
+ std::vector<MscPtr> msc_b;
+
+ try
+ {
+ msc = z120.load_msc(argv[1]);
+ }
+ catch(std::exception& exc)
+ {
+ std::cerr << "EXCEPTION: " << exc.what() << std::endl;
+ }
+
+ try
+ {
+ msc_b = z120.load_msc(argv[2]);
+ }
+ catch(std::exception& exc)
+ {
+ std::cerr << "EXCEPTION: " << exc.what() << std::endl;
+ }
+
+ MembershipAlg mem;
+ mem.set_printer(&printer);
+
+ BMscPtr bmsc = boost::dynamic_pointer_cast<BMsc>(msc_b[0]);
+
+ MscPtr result;
+
+ result = mem.diff(msc[0], bmsc);
+
+ if(result == NULL)
+ {
+std::cerr << "result was null" << std::endl;
+ if(satisfied)
+ {
+ std::cerr << "ERROR: HMSC should contain bMSC" << std::endl;
+ errors = 1;
+ }
+ else
+ std::cerr << "OK: HMSC doesn't contain bMSC" << std::endl;
+ }
+ else
+ {
+ if(satisfied)
+ std::cerr << "OK: HMSC contains bMSC" << std::endl;
+ else
+ {
+ std::cerr << "ERROR: HMSC should not contain bMSC" << std::endl;
+ errors = 1;
+ }
+
+ std::cout << std::endl;
+
+ try
+ {
+ z120.save_msc(std::cout, L"msc_diff", result);
+ }
+ catch(std::exception& exc)
+ {
+ std::cerr << "EXCEPTION: Cannot save the document: " << exc.what() << std::endl;
+ errors = 1;
+ }
+ }
+
+ return errors;
+}
Added: trunk/tests/diff/flow01.mpr
===================================================================
--- trunk/tests/diff/flow01.mpr (rev 0)
+++ trunk/tests/diff/flow01.mpr 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,22 @@
+mscdocument Drawing1;
+msc Page_1;
+inst A;
+inst B;
+inst C;
+A: instance;
+out a,0 to B;
+out b,1 to B;
+out c,3 to B;
+endinstance;
+B: instance;
+in a,0 from A;
+in b,1 from A;
+in c,3 from A;
+in a,2 from C;
+in d,4 from C;
+endinstance;
+C: instance;
+out a,2 to B;
+out d,4 to B;
+endinstance;
+endmsc;
Added: trunk/tests/diff/flow02_1.mpr
===================================================================
--- trunk/tests/diff/flow02_1.mpr (rev 0)
+++ trunk/tests/diff/flow02_1.mpr 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,13 @@
+mscdocument Drawing1;
+msc Page_1;
+inst A;
+inst B;
+A: instance;
+out a,0 to B;
+out c,3 to B;
+endinstance;
+B: instance;
+in a,0 from A;
+in c,3 from A;
+endinstance;
+endmsc;
Added: trunk/tests/diff/flow02_2.mpr
===================================================================
--- trunk/tests/diff/flow02_2.mpr (rev 0)
+++ trunk/tests/diff/flow02_2.mpr 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,13 @@
+mscdocument Drawing1;
+msc Page_1;
+inst A;
+inst B;
+A: instance;
+out b,1 to B;
+out c,3 to B;
+endinstance;
+B: instance;
+in b,1 from A;
+in c,3 from A;
+endinstance;
+endmsc;
Added: trunk/tests/diff/flow02_3.mpr
===================================================================
--- trunk/tests/diff/flow02_3.mpr (rev 0)
+++ trunk/tests/diff/flow02_3.mpr 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,13 @@
+mscdocument Drawing1;
+msc Page_1;
+inst A;
+inst B;
+A: instance;
+out a,0 to B;
+out b,1 to B;
+endinstance;
+B: instance;
+in a,0 from A;
+in b,1 from A;
+endinstance;
+endmsc;
Added: trunk/tests/diff/spec01.mpr
===================================================================
--- trunk/tests/diff/spec01.mpr (rev 0)
+++ trunk/tests/diff/spec01.mpr 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,22 @@
+mscdocument Drawing1;
+msc Page_1;
+inst A;
+inst B;
+inst C;
+C: instance;
+out a,0 to B;
+out b,1 to B;
+out c,3 to B;
+endinstance;
+B: instance;
+in a,0 from C;
+in b,1 from C;
+in c,3 from C;
+in a,2 from A;
+in d,4 from A;
+endinstance;
+A: instance;
+out a,2 to B;
+out d,4 to B;
+endinstance;
+endmsc;
Added: trunk/tests/diff/spec02.mpr
===================================================================
--- trunk/tests/diff/spec02.mpr (rev 0)
+++ trunk/tests/diff/spec02.mpr 2011-02-02 23:57:58 UTC (rev 1030)
@@ -0,0 +1,15 @@
+mscdocument Drawing1;
+msc Page_1;
+inst A;
+inst B;
+A: instance;
+out a,0 to B;
+out b,1 to B;
+out c,3 to B;
+endinstance;
+B: instance;
+in a,0 from A;
+in b,1 from A;
+in c,3 from A;
+endinstance;
+endmsc;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|