Skip to content

Commit c62fe6c

Browse files
committed
[grid] map exceptions to the correct error
1 parent d43b1ed commit c62fe6c

File tree

2 files changed

+139
-7
lines changed

2 files changed

+139
-7
lines changed

java/src/org/openqa/selenium/remote/ErrorCodec.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
package org.openqa.selenium.remote;
1919

2020
import com.google.common.base.Throwables;
21+
import com.google.common.collect.ImmutableList;
2122
import com.google.common.collect.ImmutableMap;
22-
import com.google.common.collect.ImmutableSet;
2323
import java.lang.reflect.Constructor;
24+
import java.util.List;
2425
import java.util.Map;
25-
import java.util.Set;
2626
import org.openqa.selenium.DetachedShadowRootException;
2727
import org.openqa.selenium.ElementClickInterceptedException;
2828
import org.openqa.selenium.ElementNotInteractableException;
@@ -56,8 +56,10 @@ public class ErrorCodec {
5656
private static final W3CError DEFAULT_ERROR =
5757
new W3CError("unknown error", WebDriverException.class, 500);
5858

59-
private static final Set<W3CError> ERRORS =
60-
ImmutableSet.<W3CError>builder()
59+
// note: this is a set from a logical point of view, but the implementation does rely on the order of the elements.
60+
// there is no guarantee a Set will keep the order (and we have no .equals / .hashCode implementation too).
61+
private static final List<W3CError> ERRORS =
62+
ImmutableList.<W3CError>builder()
6163
.add(new W3CError("script timeout", ScriptTimeoutException.class, 500))
6264
.add(new W3CError("detached shadow root", DetachedShadowRootException.class, 404))
6365
.add(
@@ -84,10 +86,10 @@ public class ErrorCodec {
8486
.add(new W3CError("unable to capture screen", ScreenshotException.class, 500))
8587
.add(new W3CError("unable to set cookie", UnableToSetCookieException.class, 500))
8688
.add(new W3CError("unexpected alert open", UnhandledAlertException.class, 500))
87-
.add(new W3CError("unknown error", WebDriverException.class, 500))
89+
.add(new W3CError("unsupported operation", UnsupportedCommandException.class, 404))
8890
.add(new W3CError("unknown command", UnsupportedCommandException.class, 404))
8991
.add(new W3CError("unknown method", UnsupportedCommandException.class, 405))
90-
.add(new W3CError("unsupported operation", UnsupportedCommandException.class, 404))
92+
.add(new W3CError("unknown error", WebDriverException.class, 500))
9193
.build();
9294

9395
private ErrorCodec() {
@@ -155,7 +157,7 @@ public WebDriverException decode(Map<String, Object> response) {
155157

156158
private W3CError fromThrowable(Throwable throwable) {
157159
return ERRORS.stream()
158-
.filter(err -> throwable.getClass().isAssignableFrom(err.exception))
160+
.filter(err -> err.exception.isAssignableFrom(throwable.getClass()))
159161
.findFirst()
160162
.orElse(DEFAULT_ERROR);
161163
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package org.openqa.selenium.remote;
19+
20+
import org.assertj.core.api.Assertions;
21+
import org.junit.jupiter.api.Tag;
22+
import org.junit.jupiter.api.Test;
23+
import org.openqa.selenium.DetachedShadowRootException;
24+
import org.openqa.selenium.ElementClickInterceptedException;
25+
import org.openqa.selenium.ElementNotInteractableException;
26+
import org.openqa.selenium.InsecureCertificateException;
27+
import org.openqa.selenium.InvalidArgumentException;
28+
import org.openqa.selenium.InvalidCookieDomainException;
29+
import org.openqa.selenium.InvalidElementStateException;
30+
import org.openqa.selenium.InvalidSelectorException;
31+
import org.openqa.selenium.JavascriptException;
32+
import org.openqa.selenium.NoAlertPresentException;
33+
import org.openqa.selenium.NoSuchCookieException;
34+
import org.openqa.selenium.NoSuchElementException;
35+
import org.openqa.selenium.NoSuchFrameException;
36+
import org.openqa.selenium.NoSuchSessionException;
37+
import org.openqa.selenium.NoSuchShadowRootException;
38+
import org.openqa.selenium.NoSuchWindowException;
39+
import org.openqa.selenium.ScriptTimeoutException;
40+
import org.openqa.selenium.SessionNotCreatedException;
41+
import org.openqa.selenium.StaleElementReferenceException;
42+
import org.openqa.selenium.TimeoutException;
43+
import org.openqa.selenium.UnableToSetCookieException;
44+
import org.openqa.selenium.UnhandledAlertException;
45+
import org.openqa.selenium.UnsupportedCommandException;
46+
import org.openqa.selenium.WebDriverException;
47+
import org.openqa.selenium.interactions.MoveTargetOutOfBoundsException;
48+
49+
import java.io.IOException;
50+
import java.io.UncheckedIOException;
51+
import java.text.ParseException;
52+
import java.util.Map;
53+
import java.util.UUID;
54+
55+
@Tag("UnitTests")
56+
public class ErrorCodecTest {
57+
58+
private ErrorCodec errorCodec = ErrorCodec.createDefault();
59+
60+
@Test
61+
void encodeW3cSpecExceptions() {
62+
String msg = UUID.randomUUID().toString();
63+
64+
encodeAndCheck(new ScriptTimeoutException(msg), "script timeout", msg);
65+
encodeAndCheck(new DetachedShadowRootException(msg), "detached shadow root", msg);
66+
encodeAndCheck(new ElementClickInterceptedException(msg), "element click intercepted", msg);
67+
encodeAndCheck(new ElementNotInteractableException(msg), "element not interactable", msg);
68+
encodeAndCheck(new InvalidArgumentException(msg), "invalid argument", msg);
69+
encodeAndCheck(new InvalidCookieDomainException(msg), "invalid cookie domain", msg);
70+
encodeAndCheck(new InvalidElementStateException(msg), "invalid element state", msg);
71+
encodeAndCheck(new InvalidSelectorException(msg), "invalid selector", msg);
72+
encodeAndCheck(new NoSuchSessionException(msg), "invalid session id", msg);
73+
encodeAndCheck(new InsecureCertificateException(msg), "insecure certificate", msg);
74+
encodeAndCheck(new JavascriptException(msg), "javascript error", msg);
75+
encodeAndCheck(new MoveTargetOutOfBoundsException(msg), "move target out of bounds", msg);
76+
encodeAndCheck(new NoAlertPresentException(msg), "no such alert", msg);
77+
encodeAndCheck(new NoSuchCookieException(msg), "no such cookie", msg);
78+
encodeAndCheck(new NoSuchElementException(msg), "no such element", msg);
79+
encodeAndCheck(new NoSuchFrameException(msg), "no such frame", msg);
80+
encodeAndCheck(new NoSuchShadowRootException(msg), "no such shadow root", msg);
81+
encodeAndCheck(new NoSuchWindowException(msg), "no such window", msg);
82+
encodeAndCheck(new SessionNotCreatedException(msg), "session not created", msg);
83+
encodeAndCheck(new StaleElementReferenceException(msg), "stale element reference", msg);
84+
encodeAndCheck(new TimeoutException(msg), "timeout", msg);
85+
encodeAndCheck(new ScreenshotException(msg), "unable to capture screen", msg);
86+
encodeAndCheck(new UnableToSetCookieException(msg), "unable to set cookie", msg);
87+
encodeAndCheck(new UnhandledAlertException(msg), "unexpected alert open", msg);
88+
encodeAndCheck(new UnsupportedCommandException(msg), "unsupported operation", msg);
89+
encodeAndCheck(new WebDriverException(msg), "unknown error", msg);
90+
}
91+
92+
@Test
93+
void encodeCommonUncheckedExceptions() {
94+
String msg = UUID.randomUUID().toString();
95+
96+
encodeAndCheck(new NullPointerException(msg), "unknown error", msg);
97+
encodeAndCheck(new IllegalArgumentException(msg), "unknown error", msg);
98+
encodeAndCheck(new IllegalStateException(msg), "unknown error", msg);
99+
encodeAndCheck(new java.util.NoSuchElementException(msg), "unknown error", msg);
100+
encodeAndCheck(new ArrayIndexOutOfBoundsException(msg), "unknown error", msg);
101+
encodeAndCheck(new UncheckedIOException(msg, new IOException()), "unknown error", msg);
102+
encodeAndCheck(new RuntimeException(msg), "unknown error", msg);
103+
}
104+
105+
@Test
106+
void encodeCommonCheckedExceptions() {
107+
String msg = UUID.randomUUID().toString();
108+
109+
encodeAndCheck(new IOException(msg), "unknown error", msg);
110+
encodeAndCheck(new ParseException(msg, -1), "unknown error", msg);
111+
encodeAndCheck(new InterruptedException(msg), "unknown error", msg);
112+
}
113+
114+
@Test
115+
void encodeCommonErrors() {
116+
String msg = UUID.randomUUID().toString();
117+
118+
encodeAndCheck(new OutOfMemoryError(msg), "unknown error", msg);
119+
encodeAndCheck(new StackOverflowError(msg), "unknown error", msg);
120+
encodeAndCheck(new ClassNotFoundException(msg), "unknown error", msg);
121+
}
122+
123+
void encodeAndCheck(Throwable toEncode, String expectedType, String expectedMessage) {
124+
Map<String, Object> encoded = errorCodec.encode(toEncode);
125+
Map<String, Object> value = (Map<String, Object>) encoded.get("value");
126+
127+
Assertions.assertThat(value.get("error")).isEqualTo(expectedType);
128+
Assertions.assertThat(value.get("message")).isEqualTo(toEncode.getMessage());
129+
}
130+
}

0 commit comments

Comments
 (0)