You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spark.apache.org by va...@apache.org on 2019/02/19 21:38:34 UTC
[spark] branch master updated: [SPARK-26891][YARN] Fixing flaky
test in YarnSchedulerBackendSuite
This is an automated email from the ASF dual-hosted git repository.
vanzin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git
The following commit(s) were added to refs/heads/master by this push:
new e4e4e2b [SPARK-26891][YARN] Fixing flaky test in YarnSchedulerBackendSuite
e4e4e2b is described below
commit e4e4e2b842bffba6805623f2258b27b162b451ba
Author: “attilapiros” <pi...@gmail.com>
AuthorDate: Tue Feb 19 13:22:40 2019 -0800
[SPARK-26891][YARN] Fixing flaky test in YarnSchedulerBackendSuite
The test "RequestExecutors reflects node blacklist and is serializable" is flaky because of multi threaded access of the mock task scheduler. For details check [Mockito FAQ (occasional exceptions like: WrongTypeOfReturnValue)](https://github.com/mockito/mockito/wiki/FAQ#is-mockito-thread-safe). So instead of mocking the task scheduler in the test TaskSchedulerImpl is simply subclassed.
This multithreaded access of the `nodeBlacklist()` method is coming from:
1) the unit test thread via calling of the method `prepareRequestExecutors()`
2) the `DriverEndpoint.onStart` which runs a periodic task that ends up calling this method
Existing unittest.
Closes #23801 from attilapiros/SPARK-26891.
Authored-by: “attilapiros” <pi...@gmail.com>
Signed-off-by: Marcelo Vanzin <va...@cloudera.com>
---
.../cluster/YarnSchedulerBackendSuite.scala | 37 +++++++++++++++++-----
1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/resource-managers/yarn/src/test/scala/org/apache/spark/scheduler/cluster/YarnSchedulerBackendSuite.scala b/resource-managers/yarn/src/test/scala/org/apache/spark/scheduler/cluster/YarnSchedulerBackendSuite.scala
index 5d285f8..5836944 100644
--- a/resource-managers/yarn/src/test/scala/org/apache/spark/scheduler/cluster/YarnSchedulerBackendSuite.scala
+++ b/resource-managers/yarn/src/test/scala/org/apache/spark/scheduler/cluster/YarnSchedulerBackendSuite.scala
@@ -17,6 +17,7 @@
package org.apache.spark.scheduler.cluster
import java.net.URL
+import java.util.concurrent.atomic.AtomicReference
import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse}
import scala.language.reflectiveCalls
@@ -32,15 +33,35 @@ import org.apache.spark.ui.TestFilter
class YarnSchedulerBackendSuite extends SparkFunSuite with MockitoSugar with LocalSparkContext {
+ private var yarnSchedulerBackend: YarnSchedulerBackend = _
+
+ override def afterEach(): Unit = {
+ try {
+ if (yarnSchedulerBackend != null) {
+ yarnSchedulerBackend.stop()
+ }
+ } finally {
+ super.afterEach()
+ }
+ }
+
test("RequestExecutors reflects node blacklist and is serializable") {
sc = new SparkContext("local", "YarnSchedulerBackendSuite")
- val sched = mock[TaskSchedulerImpl]
- when(sched.sc).thenReturn(sc)
- val yarnSchedulerBackend = new YarnSchedulerBackend(sched, sc) {
+ // Subclassing the TaskSchedulerImpl here instead of using Mockito. For details see SPARK-26891.
+ val sched = new TaskSchedulerImpl(sc) {
+ val blacklistedNodes = new AtomicReference[Set[String]]()
+
+ def setNodeBlacklist(nodeBlacklist: Set[String]): Unit = blacklistedNodes.set(nodeBlacklist)
+
+ override def nodeBlacklist(): Set[String] = blacklistedNodes.get()
+ }
+
+ val yarnSchedulerBackendExtended = new YarnSchedulerBackend(sched, sc) {
def setHostToLocalTaskCount(hostToLocalTaskCount: Map[String, Int]): Unit = {
this.hostToLocalTaskCount = hostToLocalTaskCount
}
}
+ yarnSchedulerBackend = yarnSchedulerBackendExtended
val ser = new JavaSerializer(sc.conf).newInstance()
for {
blacklist <- IndexedSeq(Set[String](), Set("a", "b", "c"))
@@ -50,9 +71,9 @@ class YarnSchedulerBackendSuite extends SparkFunSuite with MockitoSugar with Loc
Map("a" -> 1, "b" -> 2)
)
} {
- yarnSchedulerBackend.setHostToLocalTaskCount(hostToLocalCount)
- when(sched.nodeBlacklist()).thenReturn(blacklist)
- val req = yarnSchedulerBackend.prepareRequestExecutors(numRequested)
+ yarnSchedulerBackendExtended.setHostToLocalTaskCount(hostToLocalCount)
+ sched.setNodeBlacklist(blacklist)
+ val req = yarnSchedulerBackendExtended.prepareRequestExecutors(numRequested)
assert(req.requestedTotal === numRequested)
assert(req.nodeBlacklist === blacklist)
assert(req.hostToLocalTaskCount.keySet.intersect(blacklist).isEmpty)
@@ -75,9 +96,9 @@ class YarnSchedulerBackendSuite extends SparkFunSuite with MockitoSugar with Loc
// Before adding the "YARN" filter, should get the code from the filter in SparkConf.
assert(TestUtils.httpResponseCode(url) === HttpServletResponse.SC_BAD_GATEWAY)
- val backend = new YarnSchedulerBackend(sched, sc) { }
+ yarnSchedulerBackend = new YarnSchedulerBackend(sched, sc) { }
- backend.addWebUIFilter(classOf[TestFilter2].getName(),
+ yarnSchedulerBackend.addWebUIFilter(classOf[TestFilter2].getName(),
Map("responseCode" -> HttpServletResponse.SC_NOT_ACCEPTABLE.toString), "")
sc.ui.get.getHandlers.foreach { h =>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@spark.apache.org
For additional commands, e-mail: commits-help@spark.apache.org