/
AbstractPatienceConfiguration.scala
117 lines (108 loc) · 5.73 KB
/
AbstractPatienceConfiguration.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
* Copyright 2001-2013 Artima, Inc.
*
* Licensed 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.
*/
package org.scalatest.concurrent
import org.scalatest.time.{Span, Millis}
/**
* Trait that defines an abstract <code>patienceConfig</code> method that is implemented in <a href="PatienceConfiguration.html"><code>PatienceConfiguration</code></a> and can
* be overriden in stackable modification traits such as <a href="IntegrationPatience.html"><code>IntegrationPatience</code></a>.
*
* <p>
* The main purpose of <code>AbstractPatienceConfiguration</code> is to differentiate core <code>PatienceConfiguration</code>
* traits, such as <a href="Eventually.html"><code>Eventually</code></a> and <a href="Waiters.html"><code>Waiters</code></a>, from stackable
* modification traits for <code>PatienceConfiguration</code>s such as <code>IntegrationPatience</code>.
* Because these stackable traits extend <code>AbstractPatienceConfiguration</code>
* instead of <a href="../Suite.html"><code>Suite</code></a>, you can't simply mix in a stackable trait:
* </p>
*
* <pre class="stHighlighted">
* <span class="stReserved">class</span> <span class="stType">ExampleSpec</span> <span class="stReserved">extends</span> <span class="stType">FunSpec</span> <span class="stReserved">with</span> <span class="stType">IntegrationPatience</span> <span class="stLineComment">// Won't compile</span>
* </pre>
*
* <p>
* The previous code is undesirable because <code>IntegrationPatience</code> would have no affect on the class. Instead, you need to mix
* in a core <code>PatienceConfiguration</code> trait and mix the stackable <code>IntegrationPatience</code> trait
* into that, like this:
* </p>
*
* <pre class="stHighlighted">
* <span class="stReserved">class</span> <span class="stType">ExampleSpec</span> <span class="stReserved">extends</span> <span class="stType">FunSpec</span> <span class="stReserved">with</span> <span class="stType">Eventually</span> <span class="stReserved">with</span> <span class="stType">IntegrationPatience</span> <span class="stLineComment">// Compiles fine</span>
* </pre>
*
* <p>
* The previous code is better because <code>IntegrationPatience</code> does have an effect: it modifies the behavior
* of <code>Eventually</code>.
* </p>
*
* @author Bill Venners
*/
trait AbstractPatienceConfiguration extends ScaledTimeSpans {
/**
* Configuration object for asynchronous constructs, such as those provided by traits <a href="Eventually.html"><code>Eventually</code></a> and
* <a href="Waiters.html"><code>Waiters</code></a>.
*
* <p>
* The default values for the parameters are:
* </p>
*
* <table style="border-collapse: collapse; border: 1px solid black">
* <tr><th style="background-color: #CCCCCC; border-width: 1px; padding: 3px; text-align: center; border: 1px solid black"><strong>Configuration Parameter</strong></th><th style="background-color: #CCCCCC; border-width: 1px; padding: 3px; text-align: center; border: 1px solid black"><strong>Default Value</strong></th></tr>
* <tr>
* <td style="border-width: 1px; padding: 3px; border: 1px solid black; text-align: center">
* <code>timeout</code>
* </td>
* <td style="border-width: 1px; padding: 3px; border: 1px solid black; text-align: center">
* <code>scaled(150 milliseconds)</code>
* </td>
* </tr>
* <tr>
* <td style="border-width: 1px; padding: 3px; border: 1px solid black; text-align: center">
* <code>interval</code>
* </td>
* <td style="border-width: 1px; padding: 3px; border: 1px solid black; text-align: center">
* <code>scaled(15 milliseconds)</code>
* </td>
* </tr>
* </table>
*
* @param timeout the maximum amount of time to wait for an asynchronous operation to complete before giving up and throwing
* <code>TestFailedException</code>.
* @param interval the amount of time to sleep between each check of the status of an asynchronous operation when polling
*
* @author Bill Venners
* @author Chua Chee Seng
*/
final case class PatienceConfig(timeout: Span = scaled(Span(150, Millis)), interval: Span = scaled(Span(15, Millis))) {
/**
* <code>PatienceConfig</code> is an inner class. For some reason (like using <code>SocketReporter</code> and having
* a <code>ScalaFutures</code> test that fails), instance of this class will be serialized. But as an inner class,
* scala will add an extra <code>$outer</code> field that references actual outer class: an instance that you don't
* want make serializable.
* To avoid errors like <code>java.io.NotSerializableException: org.scalatest.verbs.BehaveWord</code>, this function
* delegates serialization to a non inner class.
*/
private def writeReplace(): Any = new AbstractPatienceConfiguration.PatienceConfigProxy(timeout, interval)
}
/**
* Returns a <code>PatienceConfig</code> value providing default configuration values if implemented and made implicit in subtraits.
*/
def patienceConfig: PatienceConfig
}
private object AbstractPatienceConfiguration extends AbstractPatienceConfiguration {
override def patienceConfig: PatienceConfig = PatienceConfig()
private final class PatienceConfigProxy(timeout: Span, interval: Span) extends Serializable {
private def readResolve(): Any = PatienceConfig(timeout, interval)
}
}