Skip to content

Commit 0c07949

Browse files
committed
WIP in kryo
1 parent 5c61000 commit 0c07949

7 files changed

Lines changed: 2330 additions & 0 deletions

File tree

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package com.codeflash;
2+
3+
import java.io.Serializable;
4+
import java.util.Objects;
5+
6+
/**
7+
* Placeholder for objects that could not be serialized.
8+
*
9+
* When KryoSerializer encounters an object that cannot be serialized
10+
* (e.g., Socket, Connection, Stream), it replaces it with a KryoPlaceholder
11+
* that stores metadata about the original object.
12+
*
13+
* This allows the rest of the object graph to be serialized while preserving
14+
* information about what was lost. If code attempts to use the placeholder
15+
* during replay tests, an error can be detected.
16+
*/
17+
public final class KryoPlaceholder implements Serializable {
18+
19+
private static final long serialVersionUID = 1L;
20+
private static final int MAX_STR_LENGTH = 100;
21+
22+
private final String objType;
23+
private final String objStr;
24+
private final String errorMsg;
25+
private final String path;
26+
27+
/**
28+
* Create a placeholder for an unserializable object.
29+
*
30+
* @param objType The fully qualified class name of the original object
31+
* @param objStr String representation of the object (may be truncated)
32+
* @param errorMsg The error message explaining why serialization failed
33+
* @param path The path in the object graph (e.g., "data.nested[0].socket")
34+
*/
35+
public KryoPlaceholder(String objType, String objStr, String errorMsg, String path) {
36+
this.objType = objType;
37+
this.objStr = truncate(objStr, MAX_STR_LENGTH);
38+
this.errorMsg = errorMsg;
39+
this.path = path;
40+
}
41+
42+
/**
43+
* Create a placeholder from an object and error.
44+
*/
45+
public static KryoPlaceholder create(Object obj, String errorMsg, String path) {
46+
String objType = obj != null ? obj.getClass().getName() : "null";
47+
String objStr = safeToString(obj);
48+
return new KryoPlaceholder(objType, objStr, errorMsg, path);
49+
}
50+
51+
private static String safeToString(Object obj) {
52+
if (obj == null) {
53+
return "null";
54+
}
55+
try {
56+
return obj.toString();
57+
} catch (Exception e) {
58+
return "<toString failed: " + e.getMessage() + ">";
59+
}
60+
}
61+
62+
private static String truncate(String s, int maxLength) {
63+
if (s == null) {
64+
return null;
65+
}
66+
if (s.length() <= maxLength) {
67+
return s;
68+
}
69+
return s.substring(0, maxLength) + "...";
70+
}
71+
72+
/**
73+
* Get the original type name of the unserializable object.
74+
*/
75+
public String getObjType() {
76+
return objType;
77+
}
78+
79+
/**
80+
* Get the string representation of the original object (may be truncated).
81+
*/
82+
public String getObjStr() {
83+
return objStr;
84+
}
85+
86+
/**
87+
* Get the error message explaining why serialization failed.
88+
*/
89+
public String getErrorMsg() {
90+
return errorMsg;
91+
}
92+
93+
/**
94+
* Get the path in the object graph where this placeholder was created.
95+
*/
96+
public String getPath() {
97+
return path;
98+
}
99+
100+
@Override
101+
public String toString() {
102+
return String.format("<KryoPlaceholder[%s] at '%s': %s>", objType, path, objStr);
103+
}
104+
105+
@Override
106+
public boolean equals(Object o) {
107+
if (this == o) return true;
108+
if (o == null || getClass() != o.getClass()) return false;
109+
KryoPlaceholder that = (KryoPlaceholder) o;
110+
return Objects.equals(objType, that.objType) &&
111+
Objects.equals(path, that.path);
112+
}
113+
114+
@Override
115+
public int hashCode() {
116+
return Objects.hash(objType, path);
117+
}
118+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.codeflash;
2+
3+
/**
4+
* Exception thrown when attempting to access or use a KryoPlaceholder.
5+
*
6+
* This exception indicates that code attempted to interact with an object
7+
* that could not be serialized and was replaced with a placeholder. This
8+
* typically means the test behavior cannot be verified for this code path.
9+
*/
10+
public class KryoPlaceholderAccessException extends RuntimeException {
11+
12+
private final String objType;
13+
private final String path;
14+
15+
public KryoPlaceholderAccessException(String message, String objType, String path) {
16+
super(message);
17+
this.objType = objType;
18+
this.path = path;
19+
}
20+
21+
/**
22+
* Get the original type name of the unserializable object.
23+
*/
24+
public String getObjType() {
25+
return objType;
26+
}
27+
28+
/**
29+
* Get the path in the object graph where the placeholder was created.
30+
*/
31+
public String getPath() {
32+
return path;
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return String.format("KryoPlaceholderAccessException[type=%s, path=%s]: %s",
38+
objType, path, getMessage());
39+
}
40+
}

0 commit comments

Comments
 (0)