1
1
package org .jenkinsci .test .acceptance .recorder ;
2
2
3
- import jakarta .inject .Inject ;
4
- import java .awt .AWTException ;
5
- import java .awt .Dimension ;
6
- import java .awt .GraphicsConfiguration ;
7
- import java .awt .GraphicsEnvironment ;
8
- import java .awt .HeadlessException ;
9
- import java .io .IOException ;
10
- import java .util .concurrent .TimeUnit ;
11
- import java .util .logging .Level ;
12
- import java .util .logging .Logger ;
13
- import org .jenkinsci .test .acceptance .junit .FailureDiagnostics ;
14
- import org .jenkinsci .test .acceptance .junit .GlobalRule ;
15
3
import org .jenkinsci .test .acceptance .utils .SystemEnvironmentVariables ;
16
- import org .junit .rules .TestWatcher ;
17
- import org .junit .runner .Description ;
18
- import org .monte .media .av .Format ;
19
- import org .monte .media .av .FormatKeys ;
20
- import org .monte .media .av .codec .video .VideoFormatKeys ;
21
- import org .monte .media .math .Rational ;
22
- import org .monte .media .screenrecorder .MouseConfigs ;
23
- import org .monte .media .screenrecorder .State ;
24
4
25
- /**
26
- * JUnit Rule that before executing a test it starts a recording current screen
27
- * and after the test is executed, it stops recording.
28
- */
29
- @ GlobalRule
30
- public class TestRecorderRule extends TestWatcher {
31
-
32
- private static final Logger logger = Logger .getLogger (TestRecorderRule .class .getName ());
33
-
34
- private static final int FRAME_RATE_PER_SEC = 60 ;
35
- private static final int BIT_DEPTH = 16 ;
36
- private static final float QUALITY_RATIO = 0.97f ;
5
+ public final class TestRecorderRule {
37
6
38
7
static final String OFF = "off" ;
39
-
40
8
static final String FAILURES = "failuresOnly" ;
41
9
static final String ALWAYS = "always" ;
42
10
@@ -46,152 +14,11 @@ public class TestRecorderRule extends TestWatcher {
46
14
"RECORDER" , DEFAULT_MODE )
47
15
.trim ();
48
16
49
- private boolean headless = false ;
50
- private FailureDiagnostics diagnostics ;
51
- private JUnitScreenRecorder screenRecorder ;
52
-
53
- @ Inject
54
- public TestRecorderRule (FailureDiagnostics diagnostics ) {
55
- this .diagnostics = diagnostics ;
56
- }
57
-
58
- @ Override
59
- protected void starting (Description description ) {
60
- if (System .getenv ("VIDEO_FOLDER" ) != null ) {
61
- // Handled by Selenium in FallbackConfig
62
- return ;
63
- }
64
- if (isRecorderEnabled ()) {
65
- startRecording (description );
66
- }
67
- }
68
-
69
- private void startRecording (Description des ) {
70
- try {
71
- GraphicsConfiguration gc = GraphicsEnvironment .getLocalGraphicsEnvironment ()
72
- .getDefaultScreenDevice ()
73
- .getDefaultConfiguration ();
74
-
75
- String mimeType = FormatKeys .MIME_QUICKTIME ;
76
- String videoFormatName = VideoFormatKeys .ENCODING_QUICKTIME_ANIMATION ;
77
- String compressorName = VideoFormatKeys .COMPRESSOR_NAME_QUICKTIME_ANIMATION ;
78
- Dimension outputDimension = gc .getBounds ().getSize ();
79
-
80
- Format outputFormatForScreenCapture = getOutputFormatForScreenCapture (
81
- videoFormatName , compressorName , outputDimension , BIT_DEPTH , QUALITY_RATIO , FRAME_RATE_PER_SEC );
82
-
83
- Format mouseFormat = new Format (
84
- FormatKeys .FrameRateKey ,
85
- Rational .valueOf (FRAME_RATE_PER_SEC ),
86
- FormatKeys .EncodingKey ,
87
- MouseConfigs .ENCODING_BLACK_CURSOR );
88
-
89
- this .screenRecorder = new JUnitScreenRecorder (
90
- gc ,
91
- gc .getBounds (),
92
- getFileFormat (mimeType ),
93
- outputFormatForScreenCapture ,
94
- mouseFormat ,
95
- null ,
96
- diagnostics );
97
- this .screenRecorder .start ();
98
- } catch (HeadlessException e ) {
99
- logger .warning ("Test recorder does not work with Headless mode" );
100
- this .headless = true ;
101
- } catch (UnsupportedOperationException | IOException | AWTException e ) {
102
- logger .log (Level .WARNING , "Exception starting test recording" , e );
103
- }
104
- }
105
-
106
- @ Override
107
- protected void succeeded (Description description ) {
108
- if (System .getenv ("VIDEO_FOLDER" ) != null ) {
109
- // Handled by Selenium in FallbackConfig
110
- return ;
111
- }
112
- if (this .screenRecorder != null && !this .headless ) {
113
- if (saveAllExecutions ()) {
114
- stopRecordingWithFinalWaiting ();
115
- } else {
116
- stopRecording ();
117
- this .screenRecorder .removeMovieFile ();
118
- }
119
- }
120
- }
121
-
122
- @ Override
123
- protected void finished (Description description ) {
124
- if (System .getenv ("VIDEO_FOLDER" ) != null ) {
125
- // Handled by Selenium in FallbackConfig
126
- return ;
127
- }
128
- stopRecordingWithFinalWaiting ();
129
- }
130
-
131
17
public static boolean isRecorderEnabled () {
132
18
return !OFF .equals (RECORDER_OPTION );
133
19
}
134
20
135
21
public static boolean saveAllExecutions () {
136
22
return ALWAYS .equals (RECORDER_OPTION );
137
23
}
138
-
139
- private void stopRecording () {
140
- stopRecording (false );
141
- }
142
-
143
- private void stopRecordingWithFinalWaiting () {
144
- stopRecording (true );
145
- }
146
-
147
- private void stopRecording (boolean waitTime ) {
148
- if (this .screenRecorder != null && !this .headless && this .screenRecorder .getState () == State .RECORDING ) {
149
- try {
150
- if (waitTime ) {
151
- waitUntilLastFramesAreRecorded ();
152
- }
153
- screenRecorder .stop ();
154
- } catch (IOException | InterruptedException e ) {
155
- logger .log (Level .WARNING , "Exception stopping test recording" , e );
156
- }
157
- }
158
- }
159
-
160
- private void waitUntilLastFramesAreRecorded () throws InterruptedException {
161
- // Values below 500 milliseconds result in no recording last frames.
162
- TimeUnit .MILLISECONDS .sleep (500 );
163
- }
164
-
165
- private Format getFileFormat (String mimeType ) {
166
- return new Format (FormatKeys .MediaTypeKey , FormatKeys .MediaType .FILE , FormatKeys .MimeTypeKey , mimeType );
167
- }
168
-
169
- private Format getOutputFormatForScreenCapture (
170
- String videoFormatName ,
171
- String compressorName ,
172
- Dimension outputDimension ,
173
- int bitDepth ,
174
- float quality ,
175
- int screenRate ) {
176
- return new Format (
177
- FormatKeys .MediaTypeKey ,
178
- FormatKeys .MediaType .VIDEO ,
179
- FormatKeys .EncodingKey ,
180
- videoFormatName ,
181
- VideoFormatKeys .CompressorNameKey ,
182
- compressorName ,
183
- VideoFormatKeys .WidthKey ,
184
- outputDimension .width ,
185
- VideoFormatKeys .HeightKey ,
186
- outputDimension .height ,
187
- VideoFormatKeys .DepthKey ,
188
- bitDepth ,
189
- FormatKeys .FrameRateKey ,
190
- Rational .valueOf (screenRate ),
191
- VideoFormatKeys .QualityKey ,
192
- quality ,
193
- FormatKeys .KeyFrameIntervalKey ,
194
- screenRate * 5 // one keyframe per 5 seconds
195
- );
196
- }
197
24
}
0 commit comments