Repository: reef
Updated Branches:
  refs/heads/master 9ce210313 -> 6f482d508


[REEF-1432] Validate Context Start failure => FailedContext Event

This addressed the issue by
  * Adding a test to verify that an Exception in ContextStartHandler
    causes a FailedContext if the Context has a parent
    and a FailedEvaluator otherwise.
  * Making changes in ContextManager and ContextRuntime to ensure
    that the Exception is properly propagated to the Driver.
  * Adding ContextException, ContextStartHandlerException, and
    have ContextClientCodeException inherit ContextException.

JIRA:
  [REEF-1432](https://issues.apache.org/jira/browse/REEF-1432)

Pull request:
  This closes #1050


Project: http://git-wip-us.apache.org/repos/asf/reef/repo
Commit: http://git-wip-us.apache.org/repos/asf/reef/commit/6f482d50
Tree: http://git-wip-us.apache.org/repos/asf/reef/tree/6f482d50
Diff: http://git-wip-us.apache.org/repos/asf/reef/diff/6f482d50

Branch: refs/heads/master
Commit: 6f482d50801e3ba2d865c0bbcebb88f27644a384
Parents: 9ce2103
Author: Andrew Chung <[email protected]>
Authored: Wed Jun 22 13:55:26 2016 -0700
Committer: Mariia Mykhailova <[email protected]>
Committed: Thu Jun 30 11:02:15 2016 -0700

----------------------------------------------------------------------
 .../Org.Apache.REEF.Common.csproj               |   2 +
 .../Context/ContextClientCodeException.cs       |  19 +-
 .../Evaluator/Context/ContextException.cs       |  46 ++++
 .../Runtime/Evaluator/Context/ContextManager.cs |  73 +++---
 .../Runtime/Evaluator/Context/ContextRuntime.cs |  76 ++++---
 .../Context/ContextStartHandlerException.cs     |  34 +++
 .../Evaluator/Context/RootContextLauncher.cs    |   1 -
 .../Runtime/Evaluator/EvaluatorRuntime.cs       |   5 +
 .../Evaluator/Task/TaskStartHandlerException.cs |   3 +
 .../Exceptions/TestSerializableException.cs     |   2 +-
 .../Failure/User/ContextStartExceptionTest.cs   | 222 +++++++++++++++++++
 .../Org.Apache.REEF.Tests.csproj                |   1 +
 12 files changed, 403 insertions(+), 81 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj 
b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
index 3582f00..d438ad1 100644
--- a/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
+++ b/lang/cs/Org.Apache.REEF.Common/Org.Apache.REEF.Common.csproj
@@ -142,9 +142,11 @@ under the License.
     <Compile Include="Files\REEFFileNames.cs" />
     <Compile Include="Runtime\Evaluator\Constants.cs" />
     <Compile Include="Runtime\Evaluator\Context\ContextClientCodeException.cs" 
/>
+    <Compile Include="Runtime\Evaluator\Context\ContextException.cs" />
     <Compile Include="Runtime\Evaluator\Context\ContextLifeCycle.cs" />
     <Compile Include="Runtime\Evaluator\Context\ContextManager.cs" />
     <Compile Include="Runtime\Evaluator\Context\ContextRuntime.cs" />
+    <Compile 
Include="Runtime\Evaluator\Context\ContextStartHandlerException.cs" />
     <Compile Include="Runtime\Evaluator\Context\ContextStartImpl.cs" />
     <Compile Include="Runtime\Evaluator\Context\ContextStopImpl.cs" />
     <Compile Include="Runtime\Evaluator\Context\RootContextLauncher.cs" />

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextClientCodeException.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextClientCodeException.cs
 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextClientCodeException.cs
index a6f9b74..df841d2 100644
--- 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextClientCodeException.cs
+++ 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextClientCodeException.cs
@@ -20,11 +20,8 @@ using Org.Apache.REEF.Utilities;
 
 namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
 {
-    internal sealed class ContextClientCodeException : Exception
+    internal sealed class ContextClientCodeException : ContextException
     {
-        private readonly string _contextId;
-        private readonly Optional<string> _parentId;
-
         /// <summary>
         /// construct the exception that caused the error
         /// </summary>
@@ -37,20 +34,8 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
                 Optional<string> parentId,
                 string message,
                 Exception cause)
-            : base("Failure in context '" + contextId + "': " + message, cause)
-        {
-            _contextId = contextId;
-            _parentId = parentId;
-        }
-
-        public string ContextId
-        {
-            get { return _contextId; }
-        }
-
-        public Optional<string> ParentId
+            : base(contextId, parentId, "Failure in context '" + contextId + 
"': " + message, cause)
         {
-            get { return _parentId; }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextException.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextException.cs 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextException.cs
new file mode 100644
index 0000000..4771e73
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextException.cs
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+using System;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
+{
+    internal abstract class ContextException : Exception
+    {
+        private readonly string _contextId;
+        private readonly Optional<string> _parentId;
+        
+        internal ContextException(
+            string contextId, Optional<string> parentId, string message, 
Exception inner) :
+            base(message, inner)
+        {
+            _contextId = contextId;
+            _parentId = parentId;
+        }
+
+        internal string ContextId
+        {
+            get { return _contextId; }
+        }
+
+        internal Optional<string> ParentId
+        {
+            get { return _parentId; }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs
index 7f9e846..28d4e06 100644
--- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextManager.cs
@@ -72,7 +72,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
                     catch (TaskClientCodeException e)
                     {
                         Utilities.Diagnostics.Exceptions.Caught(e, 
Level.Error, "Exception when trying to start a task.", LOGGER);
-                        HandleTaskException(e);
+                        HandleTaskInitializationException(e);
                     }
                 }
             }
@@ -100,13 +100,16 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
                 byte[] message = controlMessage.task_message;
                 if (controlMessage.add_context != null && 
controlMessage.remove_context != null)
                 {
-                    Utilities.Diagnostics.Exceptions.Throw(new 
InvalidOperationException("Received a message with both add and remove context. 
This is unsupported."), LOGGER);
+                    Utilities.Diagnostics.Exceptions.Throw(
+                        new InvalidOperationException(
+                            "Received a message with both add and remove 
context. This is unsupported."),
+                        LOGGER);
                 }
                 if (controlMessage.add_context != null)
                 {
                     LOGGER.Log(Level.Info, "AddContext");
                     AddContext(controlMessage.add_context);
-                    
+
                     // support submitContextAndTask()
                     if (controlMessage.start_task != null)
                     {
@@ -123,7 +126,9 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
                 }
                 else if (controlMessage.remove_context != null)
                 {
-                    LOGGER.Log(Level.Info, 
string.Format(CultureInfo.InvariantCulture, "RemoveContext with id {0}", 
controlMessage.remove_context.context_id));
+                    LOGGER.Log(Level.Info,
+                            "RemoveContext with id {0}",
+                            controlMessage.remove_context.context_id);
                     RemoveContext(controlMessage.remove_context.context_id);
                 }
                 else if (controlMessage.start_task != null)
@@ -164,7 +169,8 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
                     {
                         if (_topContext != null)
                         {
-                            context = 
_topContext.GetContextStack().FirstOrDefault(ctx => 
ctx.Id.Equals(contextMessageProto.context_id));
+                            context = _topContext.GetContextStack()
+                                    .FirstOrDefault(ctx => 
ctx.Id.Equals(contextMessageProto.context_id));
                         }
                     }
 
@@ -174,23 +180,33 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
                     }
                     else
                     {
-                        var e = new 
InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Sent 
message to unknown context {0}", contextMessageProto.context_id));
+                        var e = new InvalidOperationException(
+                            string.Format(CultureInfo.InvariantCulture,
+                                "Sent message to unknown context {0}",
+                                contextMessageProto.context_id));
                         Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
                     }
                 }
                 else
                 {
-                    InvalidOperationException e = new 
InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unknown 
task control message: {0}", controlMessage.ToString()));
+                    InvalidOperationException e = new 
InvalidOperationException(
+                        string.Format(CultureInfo.InvariantCulture,
+                            "Unknown task control message: {0}",
+                            controlMessage));
                     Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
-                } 
+                }
             }
             catch (TaskClientCodeException e)
             {
-                HandleTaskException(e);
+                HandleTaskInitializationException(e);
             }
             catch (ContextClientCodeException e)
             {
-                HandleContextException(e);
+                HandleContextException(e, e.ContextId, e.ParentId);
+            }
+            catch (ContextException e)
+            {
+                HandleContextException(e.InnerException, e.ContextId, 
e.ParentId);
             }
         }
 
@@ -344,7 +360,7 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
         ///  THIS ASSUMES THAT IT IS CALLED ON A THREAD HOLDING THE LOCK ON 
THE HeartBeatManager
         /// </summary>
         /// <param name="e"></param>
-        private void HandleTaskException(TaskClientCodeException e)
+        private void HandleTaskInitializationException(TaskClientCodeException 
e)
         {
             byte[] error;
             try
@@ -377,26 +393,27 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
             _heartBeatManager.OnNext(taskStatus);
         }
 
-        /// <summary>
-        /// THIS ASSUMES THAT IT IS CALLED ON A THREAD HOLDING THE LOCK ON THE 
HeartBeatManager
-        /// </summary>
-        /// <param name="e"></param>
-        private void HandleContextException(ContextClientCodeException e)
+        private void HandleContextException(Exception e, string contextId, 
Optional<string> parentContextId)
         {
-            LOGGER.Log(Level.Error, "ContextClientCodeException", e);
-            byte[] exception = ByteUtilities.StringToByteArrays(e.ToString());
-            ContextStatusProto contextStatusProto = new ContextStatusProto()
+            lock (_heartBeatManager)
             {
-                context_id = e.ContextId,
-                context_state = ContextStatusProto.State.FAIL,
-                error = exception
-            };
-            if (e.ParentId.IsPresent())
-            {
-                contextStatusProto.parent_id = e.ParentId.Value;
+                LOGGER.Log(Level.Warning, "ContextException", e);
+                byte[] exception = 
ByteUtilities.StringToByteArrays(e.ToString());
+                var contextStatusProto = new ContextStatusProto
+                {
+                    context_id = contextId,
+                    context_state = ContextStatusProto.State.FAIL,
+                    error = exception
+                };
+
+                if (parentContextId.IsPresent())
+                {
+                    contextStatusProto.parent_id = parentContextId.Value;
+                }
+
+                LOGGER.Log(Level.Error, "Sending Heartbeat for a failed 
context: {0}", contextStatusProto);
+                _heartBeatManager.OnNext(contextStatusProto);
             }
-            LOGGER.Log(Level.Error, "Sending Heartbeat for a failed context: 
{0}", contextStatusProto);
-            _heartBeatManager.OnNext(contextStatusProto);
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs
index eced5e2..953aa54 100644
--- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextRuntime.cs
@@ -137,7 +137,22 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
             _contextInjector = 
serviceInjector.ForkInjector(contextConfiguration);
             _contextLifeCycle = 
_contextInjector.GetInstance<ContextLifeCycle>();
             _parentContext = parentContext;
-            _contextLifeCycle.Start();
+
+            try
+            {
+                _contextLifeCycle.Start();
+            }
+            catch (Exception e)
+            {
+                const string message = "Encountered Exception in 
ContextStartHandler.";
+                if (ParentContext.IsPresent())
+                {
+                    throw new ContextStartHandlerException(
+                        Id, Optional<string>.Of(ParentContext.Value.Id), 
message, e);
+                }
+                
+                throw new ContextStartHandlerException(Id, 
Optional<string>.Empty(), message, e);
+            }
         }
 
         public string Id
@@ -199,28 +214,33 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
         /// <param name="childContextConfiguration">the new context's context 
(local) Configuration.</param>
         /// <param name="childServiceConfiguration">the new context's service 
Configuration.</param>
         /// <returns>a child context.</returns>
-        public ContextRuntime SpawnChildContext(IConfiguration 
childContextConfiguration, IConfiguration childServiceConfiguration)
+        public ContextRuntime SpawnChildContext(
+            IConfiguration childContextConfiguration, 
+            IConfiguration childServiceConfiguration = null)
         {
             lock (_contextLifeCycle)
             {
                 if (_task.IsPresent())
                 {
-                    var message =
-                        string.Format(CultureInfo.InvariantCulture, 
"Attempting to spawn a child context when an Task with id '{0}' is running", 
_task.Value.TaskId);
-
-                    var e = new InvalidOperationException(message);
-                    Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
+                    throw new InvalidOperationException(
+                        string.Format(
+                            CultureInfo.InvariantCulture, 
+                            "Attempting to spawn a child context when an Task 
with id '{0}' is running",
+                            _task.Value.TaskId));
                 }
 
                 AssertChildContextNotPresent("Attempting to instantiate a 
child context on a context that is not the topmost active context.");
                 
                 try
                 {
-                    var childServiceInjector = 
_serviceInjector.ForkInjector(childServiceConfiguration);
-                    var childContext = new 
ContextRuntime(childServiceInjector, childContextConfiguration, 
Optional<ContextRuntime>.Of(this));
+                    var childServiceInjector = childServiceConfiguration == 
null 
+                        ? _serviceInjector.ForkInjector() 
+                        : 
_serviceInjector.ForkInjector(childServiceConfiguration);
 
-                    _childContext = Optional<ContextRuntime>.Of(childContext);
-                    return childContext;
+                    _childContext = Optional<ContextRuntime>.Of(
+                        new ContextRuntime(childServiceInjector, 
childContextConfiguration, Optional<ContextRuntime>.Of(this)));
+
+                    return _childContext.Value;
                 }
                 catch (Exception e)
                 {
@@ -243,32 +263,20 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
             }
         }
 
-        /// <summary>
-        /// Spawns a new context without services of its own.
-        /// The new context will have a serviceInjector that is created by 
forking the one in this object. The
-        /// contextConfiguration is used to fork the contextInjector from that 
new serviceInjector.
-        /// </summary>
-        /// <param name="childContextConfiguration">the new context's context 
(local) Configuration.</param>
-        /// <returns> a child context.</returns>
-        public ContextRuntime SpawnChildContext(IConfiguration 
childContextConfiguration)
+        private static string GetChildContextId(IConfiguration 
childContextConfiguration)
         {
-            lock (_contextLifeCycle)
+            var contextId = string.Empty;
+            try
             {
-                if (_task.IsPresent())
-                {
-                    var message =
-                        string.Format(CultureInfo.InvariantCulture, 
"Attempting to spawn a child context when an Task with id '{0}' is running", 
_task.Value.TaskId);
-
-                    var e = new InvalidOperationException(message);
-                    Utilities.Diagnostics.Exceptions.Throw(e, LOGGER);
-                }
-
-                AssertChildContextNotPresent("Attempting to instantiate a 
child context on a context that is not the topmost active context.");
-
-                IInjector childServiceInjector = 
_serviceInjector.ForkInjector();
-                _childContext = Optional<ContextRuntime>.Of(new 
ContextRuntime(childServiceInjector, childContextConfiguration, 
Optional<ContextRuntime>.Of(this)));
-                return _childContext.Value;
+                var injector = 
TangFactory.GetTang().NewInjector(childContextConfiguration);
+                contextId = 
injector.GetNamedInstance<ContextConfigurationOptions.ContextIdentifier, 
string>();
             }
+            catch (InjectionException)
+            {
+                LOGGER.Log(Level.Error, "Unable to get Context ID from child 
ContextConfiguration. Using empty string.");
+            }
+
+            return contextId;
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextStartHandlerException.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextStartHandlerException.cs
 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextStartHandlerException.cs
new file mode 100644
index 0000000..594d12d
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/ContextStartHandlerException.cs
@@ -0,0 +1,34 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+using System;
+using Org.Apache.REEF.Utilities;
+
+namespace Org.Apache.REEF.Common.Runtime.Evaluator.Context
+{
+    /// <summary>
+    /// Exception that is thrown when the ContextStartHandler encounters an 
Exception.
+    /// </summary>
+    internal sealed class ContextStartHandlerException : ContextException
+    {
+        internal ContextStartHandlerException(
+            string contextId, Optional<string> parentId, string message, 
Exception inner) : 
+            base(contextId, parentId, message, inner)
+        {
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs
 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs
index 165bc4d..ef8795d 100644
--- 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs
+++ 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Context/RootContextLauncher.cs
@@ -22,7 +22,6 @@ using Org.Apache.REEF.Common.Runtime.Evaluator.Utils;
 using Org.Apache.REEF.Common.Services;
 using Org.Apache.REEF.Tang.Annotations;
 using Org.Apache.REEF.Tang.Formats;
-using Org.Apache.REEF.Tang.Implementations.Tang;
 using Org.Apache.REEF.Tang.Interface;
 using Org.Apache.REEF.Utilities;
 using Org.Apache.REEF.Utilities.Logging;

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorRuntime.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorRuntime.cs 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorRuntime.cs
index 80f0ce5..c1448d1 100644
--- a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorRuntime.cs
+++ b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/EvaluatorRuntime.cs
@@ -182,6 +182,11 @@ namespace Org.Apache.REEF.Common.Runtime.Evaluator
                     _contextManager.Start();
                     _heartBeatManager.OnNext();
                 }
+                catch (ContextException e)
+                {
+                    Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, 
Logger);
+                    OnException(e.InnerException);
+                }
                 catch (Exception e)
                 {
                     Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, 
Logger);

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskStartHandlerException.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskStartHandlerException.cs
 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskStartHandlerException.cs
index 07e8b10..2e83179 100644
--- 
a/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskStartHandlerException.cs
+++ 
b/lang/cs/Org.Apache.REEF.Common/Runtime/Evaluator/Task/TaskStartHandlerException.cs
@@ -19,6 +19,9 @@ using System;
 
 namespace Org.Apache.REEF.Common.Runtime.Evaluator.Task
 {
+    /// <summary>
+    /// Exception that is thrown when the TaskStartHandler encounters an 
Exception.
+    /// </summary>
     internal sealed class TaskStartHandlerException : Exception
     {
         internal TaskStartHandlerException(string message, Exception inner) : 
base(message, inner)

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/Exceptions/TestSerializableException.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/Exceptions/TestSerializableException.cs
 
b/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/Exceptions/TestSerializableException.cs
index ee9840e..cb9d6bb 100644
--- 
a/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/Exceptions/TestSerializableException.cs
+++ 
b/lang/cs/Org.Apache.REEF.Tests/Functional/Bridge/Exceptions/TestSerializableException.cs
@@ -28,7 +28,7 @@ namespace Org.Apache.REEF.Tests.Functional.Bridge.Exceptions
         {
         }
 
-        public TestSerializableException(SerializationInfo info, 
StreamingContext context)
+        private TestSerializableException(SerializationInfo info, 
StreamingContext context)
             : base(info, context)
         {
         }

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ContextStartExceptionTest.cs
----------------------------------------------------------------------
diff --git 
a/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ContextStartExceptionTest.cs
 
b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ContextStartExceptionTest.cs
new file mode 100644
index 0000000..931f3c2
--- /dev/null
+++ 
b/lang/cs/Org.Apache.REEF.Tests/Functional/Failure/User/ContextStartExceptionTest.cs
@@ -0,0 +1,222 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+using System;
+using Org.Apache.REEF.Common.Context;
+using Org.Apache.REEF.Common.Events;
+using Org.Apache.REEF.Common.Tasks;
+using Org.Apache.REEF.Driver;
+using Org.Apache.REEF.Driver.Context;
+using Org.Apache.REEF.Driver.Evaluator;
+using Org.Apache.REEF.Driver.Task;
+using Org.Apache.REEF.Tang.Annotations;
+using Org.Apache.REEF.Tang.Interface;
+using Org.Apache.REEF.Tang.Util;
+using Org.Apache.REEF.Tests.Functional.Bridge.Exceptions;
+using Org.Apache.REEF.Utilities.Logging;
+using Xunit;
+
+namespace Org.Apache.REEF.Tests.Functional.Failure.User
+{
+    [Collection("FunctionalTests")]
+    public sealed class ContextStartExceptionTest : ReefFunctionalTest
+    {
+        private static readonly Logger Logger = 
Logger.GetLogger(typeof(ContextStartExceptionTest));
+
+        private static readonly string ExpectedException = "ExpectedException";
+        private static readonly string FailEvaluatorContextId = 
"FailEvaluatorContextId";
+        private static readonly string ContextId0 = "ContextId0";
+        private static readonly string ContextId1 = "ContextId1";
+        private static readonly string TaskId = "TaskId";
+        private static readonly string CompletedTaskReceived = 
"CompletedTaskReceived";
+        private static readonly string FailedContextReceived = 
"FailedContextReceived";
+        private static readonly string FailedEvaluatorReceived = 
"FailedEvaluatorReceived";
+
+        [Fact]
+        [Trait("Priority", "1")]
+        [Trait("Category", "FunctionalGated")]
+        [Trait("Description", "Test throwing an Exception in 
ContextStartHandler should cause the Driver to receive a ContextFailed event." +
+                              "In the case of the Root Context, the Driver 
should receive a FailedEvaluator event.")]
+        public void TestContextStartException()
+        {
+            string testFolder = DefaultRuntimeFolder + TestId;
+            TestRun(
+                DriverConfiguration.ConfigurationModule
+                    .Set(DriverConfiguration.OnDriverStarted, 
GenericType<ContextStartExceptionDriver>.Class)
+                    .Set(DriverConfiguration.OnEvaluatorAllocated, 
GenericType<ContextStartExceptionDriver>.Class)
+                    .Set(DriverConfiguration.OnEvaluatorFailed, 
GenericType<ContextStartExceptionDriver>.Class)
+                    .Set(DriverConfiguration.OnContextActive, 
GenericType<ContextStartExceptionDriver>.Class)
+                    .Set(DriverConfiguration.OnContextFailed, 
GenericType<ContextStartExceptionDriver>.Class)
+                    .Set(DriverConfiguration.OnTaskCompleted, 
GenericType<ContextStartExceptionDriver>.Class)
+                    .Build(),
+                typeof(ContextStartExceptionDriver), 1, 
"ContextStartExceptionTest", "local", testFolder);
+
+            ValidateSuccessForLocalRuntime(numberOfContextsToClose: 1, 
numberOfTasksToFail: 0, numberOfEvaluatorsToFail: 1, testFolder: testFolder);
+            var driverMessages = new[]
+            {
+                CompletedTaskReceived,
+                FailedContextReceived,
+                FailedEvaluatorReceived
+            };
+
+            ValidateMessagesSuccessfullyLoggedForDriver(driverMessages, 
testFolder);
+            CleanUp(testFolder);
+        }
+
+        private sealed class ContextStartExceptionDriver : 
+            IObserver<IDriverStarted>, 
+            IObserver<IAllocatedEvaluator>,
+            IObserver<IActiveContext>,
+            IObserver<IFailedContext>,
+            IObserver<IFailedEvaluator>,
+            IObserver<ICompletedTask>
+        {
+            private readonly IEvaluatorRequestor _requestor;
+            private readonly object _lock = new object();
+            private bool _shouldSubmitFailEvaluatorContext = true;
+
+            [Inject]
+            private ContextStartExceptionDriver(IEvaluatorRequestor requestor)
+            {
+                _requestor = requestor;
+            }
+
+            public void OnNext(IDriverStarted value)
+            {
+                
_requestor.Submit(_requestor.NewBuilder().SetNumber(2).Build());
+            }
+
+            public void OnNext(IAllocatedEvaluator value)
+            {
+                lock (_lock)
+                {
+                    if (_shouldSubmitFailEvaluatorContext)
+                    {
+                        value.SubmitContext(
+                            
GetContextStartExceptionContextConfiguration(FailEvaluatorContextId));
+                        _shouldSubmitFailEvaluatorContext = false;
+                    }
+                    else
+                    {
+                        value.SubmitContext(
+                            ContextConfiguration.ConfigurationModule
+                                .Set(ContextConfiguration.Identifier, 
ContextId0)
+                                .Build());
+                    }
+                }
+            }
+
+            public void OnNext(IFailedContext value)
+            {
+                Assert.Equal(ContextId1, value.Id);
+                Assert.True(value.ParentContext.IsPresent());
+                Assert.Equal(ContextId0, value.ParentContext.Value.Id);
+
+                // TODO[JIRA REEF-1468]: Validate that Exception is properly 
serialized.
+                Logger.Log(Level.Info, FailedContextReceived);
+
+                value.ParentContext.Value.SubmitTask(
+                    TaskConfiguration.ConfigurationModule
+                        .Set(TaskConfiguration.Identifier, TaskId)
+                        .Set(TaskConfiguration.Task, 
GenericType<ContextStartExceptionTask>.Class)
+                        .Build());
+            }
+
+            public void OnNext(IFailedEvaluator value)
+            {
+                // We should not have any failed contexts since the context 
has never become active.
+                Assert.Equal(0, value.FailedContexts.Count);
+                Assert.NotNull(value.EvaluatorException.InnerException);
+                Assert.True(value.EvaluatorException.InnerException is 
TestSerializableException);
+                Assert.Equal(ExpectedException, 
value.EvaluatorException.InnerException.Message);
+                Logger.Log(Level.Info, FailedEvaluatorReceived);
+            }
+
+            public void OnNext(IActiveContext value)
+            {
+                Assert.Equal(ContextId0, value.Id);
+                
value.SubmitContext(GetContextStartExceptionContextConfiguration(ContextId1));
+            }
+
+            public void OnNext(ICompletedTask value)
+            {
+                Assert.Equal(TaskId, value.Id);
+                Assert.Equal(ContextId0, value.ActiveContext.Id);
+                Logger.Log(Level.Info, CompletedTaskReceived);
+                value.ActiveContext.Dispose();
+            }
+
+            public void OnError(Exception error)
+            {
+                throw new NotImplementedException();
+            }
+
+            public void OnCompleted()
+            {
+                throw new NotImplementedException();
+            }
+
+            private static IConfiguration 
GetContextStartExceptionContextConfiguration(string contextId)
+            {
+                return ContextConfiguration.ConfigurationModule
+                    .Set(ContextConfiguration.Identifier, contextId)
+                    .Set(ContextConfiguration.OnContextStart, 
GenericType<ContextStartExceptionHandler>.Class)
+                    .Build();
+            }
+        }
+
+        private sealed class ContextStartExceptionTask : ITask
+        {
+            [Inject]
+            private ContextStartExceptionTask()
+            {
+            }
+
+            public byte[] Call(byte[] memento)
+            {
+                return null;
+            }
+
+            public void Dispose()
+            {
+            }
+        }
+
+        private sealed class ContextStartExceptionHandler : 
IObserver<IContextStart>
+        {
+            [Inject]
+            private ContextStartExceptionHandler()
+            {
+            }
+
+            public void OnNext(IContextStart value)
+            {
+                throw new TestSerializableException(ExpectedException);
+            }
+
+            public void OnError(Exception error)
+            {
+                throw new NotImplementedException();
+            }
+
+            public void OnCompleted()
+            {
+                throw new NotImplementedException();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/reef/blob/6f482d50/lang/cs/Org.Apache.REEF.Tests/Org.Apache.REEF.Tests.csproj
----------------------------------------------------------------------
diff --git a/lang/cs/Org.Apache.REEF.Tests/Org.Apache.REEF.Tests.csproj 
b/lang/cs/Org.Apache.REEF.Tests/Org.Apache.REEF.Tests.csproj
index 4c5996a..c76a0f4 100644
--- a/lang/cs/Org.Apache.REEF.Tests/Org.Apache.REEF.Tests.csproj
+++ b/lang/cs/Org.Apache.REEF.Tests/Org.Apache.REEF.Tests.csproj
@@ -82,6 +82,7 @@ under the License.
     <Compile Include="Functional\Common\Task\ExceptionTask.cs" />
     <Compile 
Include="Functional\Failure\User\ServiceConstructorExceptionTest.cs" />
     <Compile 
Include="Functional\Failure\User\ReceiveContextMessageExceptionTest.cs" />
+    <Compile Include="Functional\Failure\User\ContextStartExceptionTest.cs" />
     <Compile Include="Functional\Failure\User\TaskCallExceptionTest.cs" />
     <Compile 
Include="Functional\Bridge\Exceptions\TestNonSerializableException.cs" />
     <Compile 
Include="Functional\Bridge\Exceptions\TestSerializableException.cs" />

Reply via email to