Skip to content

Commit

Permalink
docs(readme): Re-arrange order of sections to be more consistent with…
Browse files Browse the repository at this point in the history
… existing layout.
  • Loading branch information
mrwilson committed Feb 7, 2018
1 parent 6dcb6b7 commit 639968c
Showing 1 changed file with 15 additions and 76 deletions.
91 changes: 15 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ java -javaagent:byte-monkey.jar -jar your-java-app.jar
* **Fault**: Throw exceptions from methods that declare those exceptions
* **Latency**: Introduce latency on method-calls
* **Nullify**: Replace the first non-primitive argument to the method with *null*
* **Short-circuit**: Throw corresponding exceptions in the very beginning of try blocks
* **Short-circuit**: Throw corresponding exceptions at the very beginning of try blocks

## Options

* `mode`: What mode to run in - currently supports `fault`, `latency`, `nullify`, and `scircuit`. **Default is fault**
* `rate`: Value between 0 and 1 - how often to activate the fault. **Default is 1, i.e. 100%**
* `filter`: Only instrument packages or methods matching the (java-style) regex. **Default is .*, i.e. all methods**

byte-monkey is configured with a comma-separated key-value pair string of the options as the agent argument.

```bash
Expand All @@ -37,14 +37,6 @@ java -javaagent:byte-monkey.jar=mode:fault,rate:0.5,filter:uk/co/probablyfine/ -

The example above would run in fault mode, activating on 50% of eligible method calls, for anything in the package tree below `uk.co.probablyfine`

As for specific fault injection in try-catch blocks, you can use the following command:

```bash
java -javaagent:byte-monkey.jar=mode:scircuit,filter:package/path/ClassName/MethodName,tcindex=0 -jar your-java-app.jar
```

You can declare the exception type using `tcindex`, for example, the try block is corresponding to 2 catch blocks, then `tcindex 0` indicates the first type of exception in the catch block.

## Modes

### Fault
Expand All @@ -71,8 +63,18 @@ Methods with only primitive arguments or no arguments at all will not be affecte

### Short-circuit

Throw corresponding exceptions in the very beginning of try blocks.
What is short-circuit testing? What is this used for? You can read [this paper](https://hal.inria.fr/hal-01062969/document) or [this blog](http://blog.gluckzhang.com/archives/107/) first.
Running byte-monkey in `scircuit` mode will throw corresponding exceptions in the very beginning of try blocks.

There is a configuration option available only during this mode:

* `tcindex`: Index of which exception to throw when there are multiple catch blocks, e.g. `tcindex=0` indicates the first type of exception in the catch block. Only valid when running in **Short-circuit** mode. **Default is -1/first**

Example:
```bash
java -javaagent:byte-monkey.jar=mode:scircuit,filter:package/path/ClassName/MethodName,tcindex=0 -jar your-java-app.jar
```

You can read [this paper](https://hal.inria.fr/hal-01062969/document) or [this blog](http://blog.gluckzhang.com/archives/107/) for more information about short-circuit testing.

## Implementation Details

Expand Down Expand Up @@ -116,67 +118,4 @@ This is the core of how Byte-Monkey works:
* **11:** Create the exception if it has a default constructor, or create a wrapper exception
* **14:** Throw the exception

For modes other than `fault`, instructions 9 to 14 are replaced with mode-specific instructions.

### About the new mode to do short-circuit testing

Based on Instrumentation API and byte-monkey's codes, mainly update the `ByteMonkeyClassTransformer` to support new mode "scircuit", and add new code snippet into enum `OperationMode`.

- In `ByteMonkeyClassTransformer`: find the right position (beginning of try blocks) to inject codes

```java
switch (failureMode) {
case SCIRCUIT:
int tcIndex = arguments.tcIndex();
if (tcIndex < 0) {
cn.methods.stream()
.filter(method -> !method.name.startsWith("<"))
.filter(method -> filter.matches(cn.name, method.name))
.filter(method -> method.tryCatchBlocks.size() > 0)
.forEach(method -> {
// inject an exception in each try-catch block
// take the first exception type in catch block
// for 1 try -> n catch, we should do different injections through params
LabelNode ln = method.tryCatchBlocks.get(0).start;
int i = 0;
for (TryCatchBlockNode tc : method.tryCatchBlocks) {
if (ln == tc.start && i > 0) {
// if two try-catch-block-nodes have the same "start", it indicates that it's one try block with multiple catch
// so we should only inject one exception each time
continue;
}
InsnList newInstructions = failureMode.generateByteCode(tc, tcIndex, arguments);
method.maxStack += newInstructions.size();
method.instructions.insert(tc.start, newInstructions);
ln = tc.start;
i++;
}
});
} else {
// should work together with filter, inject an exception into specific position
...
}
break;
default:
...
}
```

- In `OperationMode`: generate exception throwing method. `DirectlyThrowException` is a method who throws an exception, the type of the exception is defined in its parameter.

```java
public InsnList generateByteCode(TryCatchBlockNode tryCatchBlock, int tcIndex, AgentArguments arguments) {
InsnList list = new InsnList();

list.add(new LdcInsnNode(tryCatchBlock.type));
list.add(new MethodInsnNode(
Opcodes.INVOKESTATIC,
"uk/co/probablyfine/bytemonkey/DirectlyThrowException",
"throwDirectly",
"(Ljava/lang/String;)V",
false // this is not a method on an interface
));

return list;
}
```
For modes other than `fault`, instructions 9 to 14 are replaced with mode-specific instructions.

1 comment on commit 639968c

@nirutgupta
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to use this framework but not able to use nullify mode
getting this error:

nirut.gupta@nirut Desktop % java -javaagent:byte-monkey.jar=mode:nullify -jar nirut.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: Local variable table overflow
Exception Details:
Location:
Myclass.fun(Ljava/util/ArrayList;)V @10: astore_1
Reason:
Local index 1 is invalid
Bytecode:
0x0000000: 1400 0cb8 0013 9900 0501 4cb2 0028 2ab6
0x0000010: 002e b200 2812 30b6 0033 b200 2812 35b6
0x0000020: 0033 b800 38b1
Stackmap Table:
same_frame_extended(@11)

at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Please sign in to comment.