|
From: <got...@us...> - 2009-04-25 20:04:23
|
Revision: 229
http://scstudio.svn.sourceforge.net/scstudio/?rev=229&view=rev
Author: gotthardp
Date: 2009-04-25 20:04:08 +0000 (Sat, 25 Apr 2009)
Log Message:
-----------
Implemented checker priority evaluation.
Modified Paths:
--------------
trunk/src/check/boundedness/universal_boundedness_checker.cpp
trunk/src/data/checker.h
trunk/src/view/visio/addon/dllmodule.rc
trunk/src/view/visio/addon/document.cpp
trunk/src/view/visio/addon/document.h
trunk/src/view/visio/scstudio.nsi
Modified: trunk/src/check/boundedness/universal_boundedness_checker.cpp
===================================================================
--- trunk/src/check/boundedness/universal_boundedness_checker.cpp 2009-04-22 21:28:52 UTC (rev 228)
+++ trunk/src/check/boundedness/universal_boundedness_checker.cpp 2009-04-25 20:04:08 UTC (rev 229)
@@ -108,7 +108,7 @@
Checker::PreconditionList UniversalBoundednessChecker::get_preconditions(MscPtr msc) const
{
Checker::PreconditionList result;
- result.push_back(CheckerPrecondition("Unique instance names", CP_RECOMMENDED));
+ result.push_back(CheckerPrecondition("Unique Instance Names", PP_RECOMMENDED));
return result;
}
Modified: trunk/src/data/checker.h
===================================================================
--- trunk/src/data/checker.h 2009-04-22 21:28:52 UTC (rev 228)
+++ trunk/src/data/checker.h 2009-04-25 20:04:08 UTC (rev 229)
@@ -49,21 +49,21 @@
*/
virtual std::string get_property_name() const = 0;
- enum CheckerPriority
+ enum PreconditionPriority
{
- CP_REQUIRED, //! error if not satisfied
- CP_RECOMMENDED, //! warning if not satisfied
- CP_DISREGARDED //! may not be satisfied
+ PP_REQUIRED, //! error if not satisfied
+ PP_RECOMMENDED, //! warning if not satisfied
+ PP_DISREGARDED //! may not be satisfied
};
struct CheckerPrecondition
{
- CheckerPrecondition(const std::string& name, CheckerPriority prio)
+ CheckerPrecondition(const std::string& name, PreconditionPriority prio)
: property_name(name), priority(prio)
{ }
std::string property_name;
- CheckerPriority priority;
+ PreconditionPriority priority;
};
//! List of properties that must be satisfied before executing the check.
typedef std::vector<CheckerPrecondition> PreconditionList;
@@ -220,12 +220,7 @@
* Holds identificators of channels represented by MessagePart of MscMessage.
*/
std::map<MessagePart,size_t> m_channels;
-
- /**
- * Use GeneralMapper::instance() to obtain instance of GeneralMapper
- */
- GeneralMapper(){};
-
+
public:
/**
Modified: trunk/src/view/visio/addon/dllmodule.rc
===================================================================
--- trunk/src/view/visio/addon/dllmodule.rc 2009-04-22 21:28:52 UTC (rev 228)
+++ trunk/src/view/visio/addon/dllmodule.rc 2009-04-25 20:04:08 UTC (rev 229)
@@ -72,8 +72,8 @@
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,2,10,0
- PRODUCTVERSION 0,2,10,0
+ FILEVERSION 0,3,0,0
+ PRODUCTVERSION 0,3,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x9L
@@ -90,13 +90,13 @@
BEGIN
VALUE "CompanyName", "Masaryk University Brno"
VALUE "FileDescription", "Microsoft Visio add-on for design and verification of Message Sequence Charts (MSC)."
- VALUE "FileVersion", "0.2.10"
+ VALUE "FileVersion", "0.3.0"
VALUE "InternalName", "scstudio.vsl"
VALUE "LegalCopyright", "(c) Petr Gotthard. All rights reserved."
VALUE "OriginalFilename", "scstudio.vsl"
VALUE "PrivateBuild", "$Revision$"
VALUE "ProductName", "Sequence Chart Studio"
- VALUE "ProductVersion", "0.2.10"
+ VALUE "ProductVersion", "0.3.0"
END
END
BLOCK "VarFileInfo"
Modified: trunk/src/view/visio/addon/document.cpp
===================================================================
--- trunk/src/view/visio/addon/document.cpp 2009-04-22 21:28:52 UTC (rev 228)
+++ trunk/src/view/visio/addon/document.cpp 2009-04-25 20:04:08 UTC (rev 229)
@@ -33,6 +33,7 @@
#include <atldlgs.h>
#include <boost/graph/adjacency_list.hpp>
+#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/topological_sort.hpp>
CDocumentMonitor::CDocumentMonitor(CStudioAddon *addon,
@@ -369,18 +370,86 @@
CheckerPtrList::const_iterator CDocumentMonitor::find_checker(const std::string& property_name) const
{
- nocase_comparator is_equal;
-
for(CheckerPtrList::const_iterator cpos = m_checkers.begin();
cpos != m_checkers.end(); cpos++)
{
- if(is_equal((*cpos)->get_property_name(), property_name))
+ if(stricmp((*cpos)->get_property_name().c_str(), property_name.c_str()) == 0)
return cpos;
}
return m_checkers.end();
}
+DWORD CDocumentMonitor::GetCheckerConfig(const char* subkey, const char* parameter, DWORD default_value) const
+{
+ TCHAR _subkey[MAX_PATH];
+ mbstowcs(_subkey, subkey, MAX_PATH);
+
+ HKEY hPathKey;
+ if(RegOpenKeyEx(HKEY_CURRENT_USER, _subkey, 0, KEY_READ, &hPathKey) != ERROR_SUCCESS)
+ return default_value;
+
+ TCHAR _parameter[MAX_PATH];
+ mbstowcs(_parameter, parameter, MAX_PATH);
+
+ DWORD valueType;
+ DWORD value;
+ DWORD valueLength = sizeof(DWORD);
+
+ if(RegQueryValueEx(hPathKey, _parameter,
+ NULL, &valueType, (LPBYTE)&value, &valueLength) != ERROR_SUCCESS)
+ {
+ // registry entry doesn't exist, use the default value
+ value = default_value;
+ }
+
+ RegCloseKey(hPathKey);
+ return value;
+}
+
+struct check_priority_t
+{
+ typedef boost::edge_property_tag kind;
+};
+
+struct max_priority_t
+{
+ typedef boost::vertex_property_tag kind;
+};
+
+template<typename MaxPriorityMap, typename CheckPriorityMap>
+class bfs_priority_visitor : public boost::default_bfs_visitor
+{
+public:
+ bfs_priority_visitor(MaxPriorityMap mmap, CheckPriorityMap cmap)
+ : m_max_priority_map(mmap), m_check_priority_map(cmap)
+ { }
+
+ // check-->dependency edge
+ template<typename Edge, typename DependencyGraph>
+ void examine_edge(Edge e, const DependencyGraph& g) const
+ {
+ // priority of the dependency
+ int priority = boost::get(m_check_priority_map, e);
+ // priority of the check
+ int src_priority = boost::get(m_max_priority_map, boost::source(e, g));
+ // effective priority is the lowest priority of [check priority, dependency priority]
+ // note: higher priority is represented by lower numbers
+ if(src_priority > priority)
+ priority = src_priority;
+
+ // priority of a dependent check is the highest effective priority of all dependencies
+ int trg_priority = boost::get(m_max_priority_map, boost::target(e, g));
+ if(trg_priority > priority)
+ boost::put(m_max_priority_map, boost::target(e, g), priority);
+ return;
+ }
+
+private:
+ MaxPriorityMap m_max_priority_map;
+ CheckPriorityMap m_check_priority_map;
+};
+
VAORC CDocumentMonitor::OnMenuRun(Visio::IVApplicationPtr vsoApp)
{
// clear the verification report
@@ -402,14 +471,49 @@
status.insert(status.begin(), m_checkers.size(), CheckExecutionStatus());
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
- boost::property<boost::vertex_color_t, boost::default_color_type> > Graph;
- Graph G(m_checkers.size());
+ // vertex properties
+ boost::property<boost::vertex_color_t, boost::default_color_type,
+ boost::property<max_priority_t, int> >,
+ // edge properties
+ boost::property<check_priority_t, int> > DependencyGraph;
+ typedef boost::graph_traits<DependencyGraph>::vertex_descriptor Vertex;
+ typedef boost::graph_traits<DependencyGraph>::edge_descriptor Edge;
+
+ size_t main_index = m_checkers.size();
+ // vertex 0..N-1 correspond to individual checkers
+ // vertex N corresponds to the user required check
+ DependencyGraph G(main_index+1);
+
+ typedef boost::property_map<DependencyGraph, max_priority_t>::type MaxPriorityMap;
+ typedef boost::property_map<DependencyGraph, check_priority_t>::type CheckPriorityMap;
+ // vertex property describing priority of the check
+ MaxPriorityMap max_priority_map = boost::get(max_priority_t(), G);
+ // edge property describing priority of the dependency
+ CheckPriorityMap check_priority_map = boost::get(check_priority_t(), G);
+
+ // user checks are always required
+ boost::put(max_priority_map, main_index, Checker::PP_REQUIRED);
+ // walk through all installed checkers
for(CheckerPtrList::const_iterator cpos = m_checkers.begin();
cpos != m_checkers.end(); cpos++)
{
size_t icheck = cpos - m_checkers.begin();
+ // initialize the property
+ boost::put(max_priority_map, icheck, Checker::PP_DISREGARDED);
+ char subkey[MAX_PATH];
+ strcpy(subkey, "Software\\Sequence Chart Studio\\Checks\\");
+ strcat(subkey, (*cpos)->get_property_name().c_str());
+
+ int user_priority = GetCheckerConfig(subkey, "Priority", 0);
+ if(user_priority < Checker::PP_DISREGARDED)
+ {
+ // add dependency for each user required check
+ std::pair<Edge,bool> res = boost::add_edge(main_index, icheck, G);
+ boost::put(check_priority_map, res.first, user_priority);
+ }
+
Checker::PreconditionList preconditions = (*cpos)->get_preconditions(msc);
// check the preconditions
for(Checker::PreconditionList::const_iterator ppos = preconditions.begin();
@@ -421,18 +525,24 @@
size_t idep = checker - m_checkers.begin();
// add dependency to the graph
// if edge (u,v) appears in the graph, then v comes before u in the ordering
- boost::add_edge(icheck, idep, G);
+ std::pair<Edge,bool> res = boost::add_edge(icheck, idep, G);
+ boost::put(check_priority_map, res.first, ppos->priority);
}
}
}
- typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
+ bfs_priority_visitor<MaxPriorityMap, CheckPriorityMap>
+ vis(max_priority_map, check_priority_map);
+ // calculate priorities of dependent checks
+ boost::breadth_first_search(G, boost::vertex(main_index, G), boost::visitor(vis));
+
typedef std::vector<Vertex> Container;
Container check_order;
try
{
- // output iterator in reverse topological order
+ // calculate execution order
+ // note: output iterator in reverse topological order
boost::topological_sort(G, std::back_inserter(check_order));
}
catch(boost::not_a_dag)
@@ -441,22 +551,29 @@
return VAORC_FAILURE;
}
- BMscPtr bmsc = boost::dynamic_pointer_cast<BMsc>(msc);
- HMscPtr hmsc = boost::dynamic_pointer_cast<HMsc>(msc);
+ enum OutputLevel
+ {
+ OL_ERROR,
+ OL_WARNING,
+ OL_NOTIFY
+ };
+ OutputLevel output_level = (OutputLevel)GetCheckerConfig("Software\\Sequence Chart Studio", "OutputLevel", 1);
- SRChannelMapperPtr srm = SRChannelMapper::instance();
-
int satisfied_count = 0;
int violated_count = 0;
+ // execute the checkers
for(Container::const_iterator cpos = check_order.begin();
cpos != check_order.end(); cpos++)
{
+ if(*cpos == main_index)
+ continue;
+
CheckerPtr msc_checker = m_checkers[*cpos];
bool all_preconditions = true;
Checker::PreconditionList preconditions = msc_checker->get_preconditions(msc);
- // check the preconditions
+ // verify the preconditions
for(Checker::PreconditionList::const_iterator ppos = preconditions.begin();
ppos != preconditions.end(); ppos++)
{
@@ -466,14 +583,14 @@
size_t idep = checker - m_checkers.begin();
if((!status[idep].executed || !status[idep].satisfied)
- && ppos->priority == Checker::CP_REQUIRED)
+ && ppos->priority == Checker::PP_REQUIRED)
{
all_preconditions = false;
}
}
else
{
- if(ppos->priority == Checker::CP_REQUIRED)
+ if(ppos->priority == Checker::PP_REQUIRED)
all_preconditions = false;
m_reportView->Print(RS_WARNING, stringize() << vsoPage->Name << ": "
@@ -489,49 +606,59 @@
continue;
}
+ SRChannelMapperPtr srm(new SRChannelMapper());
+ MscPtr result;
+
+ BMscPtr bmsc = boost::dynamic_pointer_cast<BMsc>(msc);
BMscCheckerPtr bmsc_checker = boost::dynamic_pointer_cast<BMscChecker>(msc_checker);
if(bmsc_checker != NULL && bmsc != NULL)
{
- BMscPtr result = bmsc_checker->check(bmsc, srm);
+ BMscPtr bresult = bmsc_checker->check(bmsc, srm);
status[*cpos].executed = true;
-
- if(result != NULL)
- {
- status[*cpos].satisfied = false;
- violated_count++;
-
- m_reportView->Print(RS_ERROR, stringize() << vsoPage->Name << ": "
- << msc_checker->get_property_name() << " violated.", result);
- }
- else
- {
- status[*cpos].satisfied = true;
- satisfied_count++;
-
- m_reportView->Print(RS_NOTICE, stringize() << vsoPage->Name << ": "
- << msc_checker->get_property_name() << " satisfied.");
- }
+ // note: the explicit cast is a workaround for a bug in Visual Studio .NET
+ result = boost::dynamic_pointer_cast<Msc>(bresult);
}
+ HMscPtr hmsc = boost::dynamic_pointer_cast<HMsc>(msc);
HMscCheckerPtr hmsc_checker = boost::dynamic_pointer_cast<HMscChecker>(msc_checker);
if(hmsc_checker != NULL && hmsc != NULL)
{
- HMscPtr result = hmsc_checker->check(hmsc, srm);
+ HMscPtr hresult = hmsc_checker->check(hmsc, srm);
status[*cpos].executed = true;
+ result = boost::dynamic_pointer_cast<Msc>(hresult);
+ }
- if(result != NULL)
+ if(result != NULL)
+ {
+ status[*cpos].satisfied = false;
+ violated_count++;
+
+ // report failure of
+ // - user required tests
+ // - required dependencies of required tests
+ if(boost::get(max_priority_map, *cpos) == Checker::PP_REQUIRED)
{
- status[*cpos].satisfied = false;
- violated_count++;
-
m_reportView->Print(RS_ERROR, stringize() << vsoPage->Name << ": "
<< msc_checker->get_property_name() << " violated.", result);
}
- else
+
+ // if enabled, report failure all executed tests
+ if(boost::get(max_priority_map, *cpos) == Checker::PP_RECOMMENDED
+ && output_level >= OL_WARNING)
{
- status[*cpos].satisfied = true;
- satisfied_count++;
+ m_reportView->Print(RS_WARNING, stringize() << vsoPage->Name << ": "
+ << msc_checker->get_property_name() << " violated.", result);
+ }
+ }
+ else
+ {
+ status[*cpos].satisfied = true;
+ satisfied_count++;
+ // if enabled, report success of user required tests
+ if(boost::get(max_priority_map, *cpos) == Checker::PP_REQUIRED
+ && output_level >= OL_NOTIFY)
+ {
m_reportView->Print(RS_NOTICE, stringize() << vsoPage->Name << ": "
<< msc_checker->get_property_name() << " satisfied.");
}
Modified: trunk/src/view/visio/addon/document.h
===================================================================
--- trunk/src/view/visio/addon/document.h 2009-04-22 21:28:52 UTC (rev 228)
+++ trunk/src/view/visio/addon/document.h 2009-04-25 20:04:08 UTC (rev 229)
@@ -73,6 +73,7 @@
CheckerPtrList m_checkers;
CheckerPtrList::const_iterator find_checker(const std::string& property_name) const;
+ DWORD GetCheckerConfig(const char* subkey, const char* parameter, DWORD default_value) const;
CStudioAddon *m_addon;
Visio::IVApplicationPtr m_vsoApp;
Modified: trunk/src/view/visio/scstudio.nsi
===================================================================
--- trunk/src/view/visio/scstudio.nsi 2009-04-22 21:28:52 UTC (rev 228)
+++ trunk/src/view/visio/scstudio.nsi 2009-04-25 20:04:08 UTC (rev 229)
@@ -21,7 +21,7 @@
; -- General ---------------------------
-!define VERSION "0.2.10"
+!define VERSION "0.3.0"
Name "Sequence Chart Studio"
OutFile "scstudio-setup-${VERSION}.exe"
@@ -30,6 +30,7 @@
!define RegMainPath "Software\Sequence Chart Studio"
!define RegModulesPath "Software\Sequence Chart Studio\Modules"
+!define RegChecksPath "Software\Sequence Chart Studio\Checks"
!define Visio11RegPath "Software\Microsoft\Office\11.0\Visio"
!define Visio12RegPath "Software\Microsoft\Office\12.0\Visio"
@@ -143,6 +144,7 @@
DeleteRegKey HKCU "${RegMainPath}"
; register modules
WriteRegStr HKCU '${RegMainPath}' 'ModulesPath' '$INSTDIR\bin'
+ WriteRegDWORD HKCU '${RegMainPath}' 'OutputLevel' '2'
WriteRegStr HKCU '${RegModulesPath}' 'sc_boundedness' 'scboundedness.dll'
WriteRegStr HKCU '${RegModulesPath}' 'sc_liveness' 'scliveness.dll'
WriteRegStr HKCU '${RegModulesPath}' 'sc_order' 'scorder.dll'
@@ -150,6 +152,14 @@
WriteRegStr HKCU '${RegModulesPath}' 'sc_race' 'scrace.dll'
WriteRegStr HKCU '${RegModulesPath}' 'sc_z120' 'scZ120.dll'
WriteRegStr HKCU '${RegModulesPath}' 'sc_engmann' 'scengmann.dll'
+ ; configure checks
+ WriteRegDWORD HKCU '${RegChecksPath}\Acyclic' 'Priority' '0'
+ WriteRegDWORD HKCU '${RegChecksPath}\Deadlock' 'Priority' '0'
+ WriteRegDWORD HKCU '${RegChecksPath}\FIFO' 'Priority' '0'
+ WriteRegDWORD HKCU '${RegChecksPath}\Livelock' 'Priority' '0'
+ WriteRegDWORD HKCU '${RegChecksPath}\Race Conditions' 'Priority' '0'
+ WriteRegDWORD HKCU '${RegChecksPath}\Unique Instance Names' 'Priority' '2'
+ WriteRegDWORD HKCU '${RegChecksPath}\Universal Boundedness' 'Priority' '0'
; Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|