From acdea4c90f70cd847d8266b79ab93cf34eb522ae Mon Sep 17 00:00:00 2001
From: Benjamin Wynne <bwynne@cern.ch>
Date: Thu, 4 Jan 2018 17:46:49 +0100
Subject: [PATCH] Prevent view nesting. Add test for this, and for standard
 execution

Former-commit-id: 4fac85286da83258621cd40f4f0fb2a83594f4fc
---
 Control/AthViews/AthViews/ViewHelper.h        | 12 ++-
 Control/AthViews/CMakeLists.txt               |  6 ++
 Control/AthViews/share/ViewNest.py            | 79 +++++++++++++++++++
 Control/AthViews/test/test_view_nest_fail.sh  | 10 +++
 Control/AthViews/test/test_view_scheduling.sh |  5 ++
 5 files changed, 108 insertions(+), 4 deletions(-)
 create mode 100644 Control/AthViews/share/ViewNest.py
 create mode 100755 Control/AthViews/test/test_view_nest_fail.sh
 create mode 100755 Control/AthViews/test/test_view_scheduling.sh

diff --git a/Control/AthViews/AthViews/ViewHelper.h b/Control/AthViews/AthViews/ViewHelper.h
index bbc6572d3d4..99b01f01ce4 100644
--- a/Control/AthViews/AthViews/ViewHelper.h
+++ b/Control/AthViews/AthViews/ViewHelper.h
@@ -106,22 +106,26 @@ namespace ViewHelper
   inline StatusCode ScheduleViews( std::vector< SG::View* > const& ViewVector, std::string const& NodeName,
       EventContext const& SourceContext, IScheduler * Scheduler )
   {
+    //Prevent view nesting - test if source context has view attached
+    Atlas::ExtendedEventContext const* extendedContext = SourceContext.template getExtension<Atlas::ExtendedEventContext>();
+    if ( dynamic_cast< SG::View* >( extendedContext->proxy() ) )
+    {
+      return StatusCode::FAILURE;
+    }
+
     //Retrieve the scheduler
     if ( !Scheduler )
     {
       return StatusCode::FAILURE;
     }
 
-    //Retrieve existing extended context
-    unsigned int conditionsRun = SourceContext.template getExtension<Atlas::ExtendedEventContext>()->conditionsRun();
-
     if ( ViewVector.size() )
     {
       for ( SG::View* view : ViewVector )
       {
         //Make a context with the view attached
         EventContext * viewContext = new EventContext( SourceContext );
-        viewContext->setExtension( Atlas::ExtendedEventContext( view, conditionsRun ) );
+        viewContext->setExtension( Atlas::ExtendedEventContext( view, extendedContext->conditionsRun() ) );
 
         //Attach the view to the named node
         StatusCode sc = Scheduler->scheduleEventView( &SourceContext, NodeName, viewContext );
diff --git a/Control/AthViews/CMakeLists.txt b/Control/AthViews/CMakeLists.txt
index ccbc49a0b49..3340f0eb279 100644
--- a/Control/AthViews/CMakeLists.txt
+++ b/Control/AthViews/CMakeLists.txt
@@ -45,6 +45,12 @@ atlas_add_test( ViewLinking_test
 		LINK_LIBRARIES ${TBB_LIBRARIES}
 		AthViews TestTools )
 
+atlas_add_test( ViewScheduling SCRIPT test/test_view_scheduling.sh
+                EXTRA_PATTERNS "INFO 109" )
+
+atlas_add_test( ViewNestFail SCRIPT test/test_view_nest_fail.sh
+                EXTRA_PATTERNS "Execution of algorithm nest_alg failed" )
+
 # Install files from the package:
 atlas_install_headers( AthViews )
 atlas_install_joboptions( share/*.py )
diff --git a/Control/AthViews/share/ViewNest.py b/Control/AthViews/share/ViewNest.py
new file mode 100644
index 00000000000..de997372eb0
--- /dev/null
+++ b/Control/AthViews/share/ViewNest.py
@@ -0,0 +1,79 @@
+#
+#  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+#
+
+###############################################################
+#
+# Job options file
+#
+# Based on AthExStoreGateExamples
+#
+#==============================================================
+
+#--------------------------------------------------------------
+# ATLAS default Application Configuration options
+#--------------------------------------------------------------
+
+# Configure the scheduler
+from AthenaCommon.AlgScheduler import AlgScheduler
+AlgScheduler.ShowControlFlow( True )
+AlgScheduler.ShowDataDependencies( True )
+
+# Control flow
+from AthenaCommon.AlgSequence import AthSequencer
+l2ViewAlgorithms = AthSequencer( "l2ViewAlgorithms" )
+l2ViewAlgorithms.ModeOR = False
+l2ViewAlgorithms.Sequential = False
+l2ViewAlgorithms.StopOverride = False
+l1ViewAlgorithms = AthSequencer( "l1ViewAlgorithms" )
+l1ViewAlgorithms.ModeOR = False
+l1ViewAlgorithms.Sequential = True
+l1ViewAlgorithms.StopOverride = False
+makeViewSequence = AthSequencer( "makeViewSequence" )
+makeViewSequence.ModeOR = False
+makeViewSequence.Sequential = True
+makeViewSequence.StopOverride = False
+
+# Event-level algorithm sequence
+from AthenaCommon.AlgSequence import AlgSequence
+job = AlgSequence()
+
+# Make views
+makeViewSequence += CfgMgr.AthViews__ViewSubgraphAlg("make_alg")
+makeViewSequence.make_alg.ViewBaseName = "view"
+makeViewSequence.make_alg.ViewNumber = 10
+makeViewSequence.make_alg.ViewNodeName = l1ViewAlgorithms.name()
+makeViewSequence.make_alg.Scheduler = AlgScheduler.getScheduler()
+
+# View algorithms
+ViewTest = CfgMgr.AthViews__ViewTestAlg("view_test")
+l1ViewAlgorithms += ViewTest
+#
+l1ViewAlgorithms += CfgMgr.AthViews__ViewSubgraphAlg("nest_alg")
+l1ViewAlgorithms.nest_alg.ViewBaseName = "viewView"
+l1ViewAlgorithms.nest_alg.ViewNumber = 10
+l1ViewAlgorithms.nest_alg.ViewNodeName = l2ViewAlgorithms.name()
+l1ViewAlgorithms.nest_alg.Scheduler = AlgScheduler.getScheduler()
+#
+ViewViewTest = CfgMgr.AthViews__ViewTestAlg("viewView_test")
+l2ViewAlgorithms += ViewViewTest
+
+# Add the view algorithms to the job
+l1ViewAlgorithms += l2ViewAlgorithms
+makeViewSequence += l1ViewAlgorithms
+
+# Merge views
+makeViewSequence += CfgMgr.AthViews__ViewMergeAlg("merge_alg")
+
+job += makeViewSequence
+
+#--------------------------------------------------------------
+# Event related parameters
+#--------------------------------------------------------------
+theApp.EvtMax = 10
+
+#==============================================================
+#
+# End of job options file
+#
+###############################################################
diff --git a/Control/AthViews/test/test_view_nest_fail.sh b/Control/AthViews/test/test_view_nest_fail.sh
new file mode 100755
index 00000000000..84caa738f68
--- /dev/null
+++ b/Control/AthViews/test/test_view_nest_fail.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# art-type: build
+# art-ci: master
+
+# We expect this command to fail, so invert the exit code
+if athena.py --threads=1 AthViews/ViewNest.py; then
+  exit 1
+else
+  exit 0
+fi
diff --git a/Control/AthViews/test/test_view_scheduling.sh b/Control/AthViews/test/test_view_scheduling.sh
new file mode 100755
index 00000000000..99db2e07108
--- /dev/null
+++ b/Control/AthViews/test/test_view_scheduling.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# art-type: build
+# art-ci: master
+
+athena.py --threads=1 AthViews/ViewScheduling.py
-- 
GitLab