Skip to content

Commit 50c6f94

Browse files
committed
Adding custom error messages that Promises&Future are not serializable
* Complete with regression test verifying that they all throw NotSerializableException
1 parent 6514830 commit 50c6f94

File tree

4 files changed

+47
-1
lines changed

4 files changed

+47
-1
lines changed

src/library/scala/concurrent/Future.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
package scala.concurrent
1414

1515
import scala.language.higherKinds
16-
import java.util.concurrent.{CountDownLatch, TimeUnit}
16+
import java.util.concurrent.{ CountDownLatch, TimeUnit }
1717
import java.util.concurrent.atomic.AtomicReference
1818

1919
import scala.util.control.{NonFatal, NoStackTrace}

src/library/scala/concurrent/impl/Promise.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import scala.runtime.NonLocalReturnControl
2121
import java.util.concurrent.locks.AbstractQueuedSynchronizer
2222
import java.util.concurrent.atomic.{ AtomicReference, AtomicBoolean }
2323
import java.util.Objects.requireNonNull
24+
import java.io.{ NotSerializableException, IOException, ObjectInputStream, ObjectOutputStream }
2425

2526
/**
2627
* Latch used to implement waiting on a DefaultPromise's result.
@@ -331,6 +332,15 @@ private[concurrent] object Promise {
331332
next.unlink(resolved)
332333
} else tryComplete0(state, resolved)
333334
}
335+
336+
@throws[IOException]
337+
private def writeObject(out: ObjectOutputStream): Unit =
338+
throw new NotSerializableException("Promises and Futures cannot be serialized")
339+
340+
@throws[IOException]
341+
@throws[ClassNotFoundException]
342+
private def readObject(in: ObjectInputStream): Unit =
343+
throw new NotSerializableException("Promises and Futures cannot be deserialized")
334344
}
335345

336346
// Constant byte tags for unpacking transformation function inputs or outputs

test/files/jvm/future-spec/FutureTests.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,25 @@ class FutureTests extends MinimalScalaTest {
7878
}
7979

8080
"Futures" should {
81+
82+
"not be serializable" in {
83+
84+
def verifyNonSerializabilityFor(p: Future[_]): Unit = {
85+
import java.io._
86+
val out = new ObjectOutputStream(new ByteArrayOutputStream())
87+
intercept[NotSerializableException] {
88+
out.writeObject(p)
89+
}
90+
}
91+
verifyNonSerializabilityFor(Await.ready(Future.unit.map(_ => ())(ExecutionContext.global), defaultTimeout))
92+
verifyNonSerializabilityFor(Future.unit)
93+
verifyNonSerializabilityFor(Future.failed(new NullPointerException))
94+
verifyNonSerializabilityFor(Future.successful("test"))
95+
verifyNonSerializabilityFor(Future.fromTry(Success("test")))
96+
verifyNonSerializabilityFor(Future.fromTry(Failure(new NullPointerException)))
97+
verifyNonSerializabilityFor(Future.never)
98+
}
99+
81100
"have proper toString representations" in {
82101
import ExecutionContext.Implicits.global
83102
val s = 5

test/files/jvm/future-spec/PromiseTests.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,23 @@ class PromiseTests extends MinimalScalaTest {
131131
futureWithResult(_(future, result))
132132
}
133133

134+
"A Promise should not be serializable" should {
135+
136+
def verifyNonSerializabilityFor(p: Promise[_]): Unit = {
137+
import java.io._
138+
val out = new ObjectOutputStream(new ByteArrayOutputStream())
139+
intercept[NotSerializableException] {
140+
out.writeObject(p)
141+
}.getMessage mustBe "Promises and Futures cannot be serialized"
142+
}
143+
144+
verifyNonSerializabilityFor(Promise[Unit]())
145+
verifyNonSerializabilityFor(Promise.failed(new NullPointerException))
146+
verifyNonSerializabilityFor(Promise.successful("test"))
147+
verifyNonSerializabilityFor(Promise.fromTry(Success("test")))
148+
verifyNonSerializabilityFor(Promise.fromTry(Failure(new NullPointerException)))
149+
}
150+
134151
def futureWithResult(f: ((Future[Any], Any) => Unit) => Unit): Unit = {
135152

136153
"be completed" in { f((future, _) => future.isCompleted mustBe (true)) }

0 commit comments

Comments
 (0)