mirror of https://github.com/chaos-mesh/chaosd.git
				
				
				
			Merge branch 'main' into file
This commit is contained in:
		
						commit
						684c9f93b2
					
				|  | @ -48,9 +48,10 @@ jobs: | |||
|         run: | | ||||
| 
 | ||||
|           # download tools | ||||
|           curl -fsSL -o byteman.tar.gz https://mirrors.chaos-mesh.org/latest/byteman.tar.gz | ||||
|           BYTEMAN_DIR=byteman-chaos-mesh-download-v4.0.18-0.9 | ||||
|           curl -fsSL -o ${BYTEMAN_DIR}.tar.gz https://mirrors.chaos-mesh.org/${BYTEMAN_DIR}.tar.gz | ||||
|           curl -fsSL -o stress-ng https://mirrors.chaos-mesh.org/latest/stress-ng | ||||
|           tar zxvf byteman.tar.gz | ||||
|           tar zxvf ${BYTEMAN_DIR}.tar.gz | ||||
|           chmod +x ./stress-ng | ||||
| 
 | ||||
|           # prepare package | ||||
|  | @ -58,7 +59,7 @@ jobs: | |||
|           mkdir chaosd-latest-linux-amd64/tools | ||||
|           mv bin/chaosd chaosd-latest-linux-amd64/ | ||||
|           mv bin/PortOccupyTool chaosd-latest-linux-amd64/tools/ | ||||
|           mv byteman chaosd-latest-linux-amd64/tools/ | ||||
|           mv ${BYTEMAN_DIR} chaosd-latest-linux-amd64/tools/byteman | ||||
|           mv stress-ng chaosd-latest-linux-amd64/tools/ | ||||
| 
 | ||||
|           # upload package | ||||
|  |  | |||
|  | @ -49,9 +49,10 @@ jobs: | |||
|           GIT_TAG=${GITHUB_REF##*/} | ||||
| 
 | ||||
|           # download tools | ||||
|           curl -fsSL -o byteman.tar.gz https://mirrors.chaos-mesh.org/latest/byteman.tar.gz | ||||
|           BYTEMAN_DIR=byteman-chaos-mesh-download-v4.0.18-0.9 | ||||
|           curl -fsSL -o ${BYTEMAN_DIR}.tar.gz https://mirrors.chaos-mesh.org/${BYTEMAN_DIR}.tar.gz | ||||
|           curl -fsSL -o stress-ng https://mirrors.chaos-mesh.org/latest/stress-ng | ||||
|           tar zxvf byteman.tar.gz | ||||
|           tar zxvf ${BYTEMAN_DIR}.tar.gz | ||||
|           chmod +x ./stress-ng | ||||
| 
 | ||||
|           # prepare package | ||||
|  | @ -59,7 +60,7 @@ jobs: | |||
|           mkdir chaosd-${GIT_TAG}-linux-amd64/tools | ||||
|           mv bin/chaosd chaosd-${GIT_TAG}-linux-amd64/ | ||||
|           mv bin/PortOccupyTool chaosd-${GIT_TAG}-linux-amd64/tools/ | ||||
|           mv byteman chaosd-${GIT_TAG}-linux-amd64/tools/ | ||||
|           mv ${BYTEMAN_DIR} chaosd-${GIT_TAG}-linux-amd64/tools/byteman | ||||
|           mv stress-ng chaosd-${GIT_TAG}-linux-amd64/tools/ | ||||
| 
 | ||||
|           # upload package | ||||
|  |  | |||
							
								
								
									
										101
									
								
								pkg/core/jvm.go
								
								
								
								
							
							
						
						
									
										101
									
								
								pkg/core/jvm.go
								
								
								
								
							|  | @ -23,6 +23,7 @@ import ( | |||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	// jvm action
 | ||||
| 	JVMLatencyAction   = "latency" | ||||
| 	JVMExceptionAction = "exception" | ||||
| 	JVMReturnAction    = "return" | ||||
|  | @ -30,21 +31,56 @@ const ( | |||
| 	JVMGCAction        = "gc" | ||||
| 	JVMRuleFileAction  = "rule-file" | ||||
| 	JVMRuleDataAction  = "rule-data" | ||||
| 
 | ||||
| 	// for action 'gc' and 'stress'
 | ||||
| 	GCHelper     = "org.chaos_mesh.byteman.helper.GCHelper" | ||||
| 	StressHelper = "org.chaos_mesh.byteman.helper.StressHelper" | ||||
| 
 | ||||
| 	// the trigger point for 'gc' and 'stress'
 | ||||
| 	TriggerClass  = "org.chaos_mesh.chaos_agent.TriggerThread" | ||||
| 	TriggerMethod = "triggerFunc" | ||||
| ) | ||||
| 
 | ||||
| // byteman rule template
 | ||||
| const ( | ||||
| 	SimpleRuleTemplate = ` | ||||
| RULE {{.Name}} | ||||
| CLASS {{.Class}} | ||||
| METHOD {{.Method}} | ||||
| AT ENTRY | ||||
| IF true | ||||
| DO | ||||
| 	{{.Do}}; | ||||
| ENDRULE | ||||
| ` | ||||
| 
 | ||||
| 	CompleteRuleTemplate = ` | ||||
| RULE {{.Name}} | ||||
| CLASS {{.Class}} | ||||
| METHOD {{.Method}} | ||||
| HELPER {{.Helper}} | ||||
| AT ENTRY | ||||
| BIND {{.Bind}}; | ||||
| IF {{.Condition}} | ||||
| DO | ||||
| 	{{.Do}}; | ||||
| ENDRULE | ||||
| ` | ||||
| ) | ||||
| 
 | ||||
| type JVMCommand struct { | ||||
| 	CommonAttackConfig | ||||
| 
 | ||||
| 	JVMCommonSpec | ||||
| 
 | ||||
| 	JVMClassMethodSpec | ||||
| 
 | ||||
| 	JVMStressSpec | ||||
| 
 | ||||
| 	// rule name, should be unique, and will generate by chaosd automatically
 | ||||
| 	Name string `json:"name,omitempty"` | ||||
| 
 | ||||
| 	// Java class
 | ||||
| 	Class string `json:"class,omitempty"` | ||||
| 
 | ||||
| 	// the method in Java class
 | ||||
| 	Method string `json:"method,omitempty"` | ||||
| 
 | ||||
| 	// fault action, values can be latency, exception, return, stress
 | ||||
| 	// fault action, values can be latency, exception, return, stress, gc, rule-file, rule-data
 | ||||
| 	Action string `json:"action,omitempty"` | ||||
| 
 | ||||
| 	// the return value for action 'return'
 | ||||
|  | @ -56,35 +92,50 @@ type JVMCommand struct { | |||
| 	// the latency duration for action 'latency'
 | ||||
| 	LatencyDuration int `json:"latency,omitempty"` | ||||
| 
 | ||||
| 	// the CPU core number, only set it when action is stress
 | ||||
| 	CPUCount int `json:"cpu-count,omitempty"` | ||||
| 	// btm rule file path for action 'rule-file'
 | ||||
| 	RuleFile string `json:"rule-file,omitempty"` | ||||
| 
 | ||||
| 	// the memory type to be located, only set it when action is stress, the value can be 'stack' or 'heap'
 | ||||
| 	MemoryType string `json:"mem-type,omitempty"` | ||||
| 
 | ||||
| 	// attach or agent
 | ||||
| 	Type string | ||||
| 	// RuleData used to save the rule file's data, will use it when recover, for action 'rule-data'
 | ||||
| 	RuleData string `json:"rule-data,omitempty"` | ||||
| } | ||||
| 
 | ||||
| type JVMCommonSpec struct { | ||||
| 	// the port of agent server
 | ||||
| 	Port int `json:"port,omitempty"` | ||||
| 
 | ||||
| 	// the pid of Java process which needs to attach
 | ||||
| 	// the pid of Java process which need to attach
 | ||||
| 	Pid int `json:"pid,omitempty"` | ||||
| } | ||||
| 
 | ||||
| 	// btm rule file path
 | ||||
| 	RuleFile string `json:"rule-file,omitempty"` | ||||
| type JVMClassMethodSpec struct { | ||||
| 	// Java class
 | ||||
| 	Class string `json:"class,omitempty"` | ||||
| 
 | ||||
| 	// RuleData used to save the rule file's data, will use it when recover
 | ||||
| 	RuleData string `json:"rule-data,omitempty"` | ||||
| 	// the method in Java class
 | ||||
| 	Method string `json:"method,omitempty"` | ||||
| } | ||||
| 
 | ||||
| 	// below is only used for template
 | ||||
| 	Do string `json:"-"` | ||||
| type JVMStressSpec struct { | ||||
| 	// the CPU core number need to use, only set it when action is stress
 | ||||
| 	CPUCount int `json:"cpu-count,omitempty"` | ||||
| 
 | ||||
| 	StressType string `json:"-"` | ||||
| 	// the memory type need to locate, only set it when action is stress, the value can be 'stack' or 'heap'
 | ||||
| 	MemoryType string `json:"mem-type,omitempty"` | ||||
| } | ||||
| 
 | ||||
| 	StressValueName string `json:"-"` | ||||
| type BytemanTemplateSpec struct { | ||||
| 	Name      string | ||||
| 	Class     string | ||||
| 	Method    string | ||||
| 	Helper    string | ||||
| 	Bind      string | ||||
| 	Condition string | ||||
| 	Do        string | ||||
| 
 | ||||
| 	StressValue string `json:"-"` | ||||
| 	// below is only used for stress template
 | ||||
| 	StressType      string | ||||
| 	StressValueName string | ||||
| 	StressValue     string | ||||
| } | ||||
| 
 | ||||
| func (j *JVMCommand) Validate() error { | ||||
|  | @ -108,7 +159,7 @@ func (j *JVMCommand) Validate() error { | |||
| 			return errors.New("class not provided") | ||||
| 		} | ||||
| 
 | ||||
| 		if len(j.Method) == 0 { | ||||
| 		if len(j.JVMClassMethodSpec.Method) == 0 { | ||||
| 			return errors.New("method not provided") | ||||
| 		} | ||||
| 	case JVMRuleFileAction: | ||||
|  |  | |||
|  | @ -32,62 +32,86 @@ func TestJVMCommand(t *testing.T) { | |||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid: 1234, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"action not provided", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:    1234, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: "test", | ||||
| 			}, | ||||
| 			"action test not supported", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:    1234, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: JVMLatencyAction, | ||||
| 			}, | ||||
| 			"class not provided", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:    1234, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: JVMExceptionAction, | ||||
| 				Class:  "test", | ||||
| 				JVMClassMethodSpec: JVMClassMethodSpec{ | ||||
| 					Class: "test", | ||||
| 				}, | ||||
| 			}, | ||||
| 			"method not provided", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:    1234, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: JVMExceptionAction, | ||||
| 				Class:  "test", | ||||
| 				Method: "test", | ||||
| 				JVMClassMethodSpec: JVMClassMethodSpec{ | ||||
| 					Class:  "test", | ||||
| 					Method: "test", | ||||
| 				}, | ||||
| 			}, | ||||
| 			"", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:    1234, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: JVMStressAction, | ||||
| 			}, | ||||
| 			"must set one of cpu-count and mem-type", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:        1234, | ||||
| 				Action:     JVMStressAction, | ||||
| 				CPUCount:   1, | ||||
| 				MemoryType: "heap", | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: JVMStressAction, | ||||
| 				JVMStressSpec: JVMStressSpec{ | ||||
| 					CPUCount:   1, | ||||
| 					MemoryType: "heap", | ||||
| 				}, | ||||
| 			}, | ||||
| 			"inject stress on both CPU and memory is not support now", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&JVMCommand{ | ||||
| 				Pid:      1234, | ||||
| 				Action:   JVMStressAction, | ||||
| 				CPUCount: 1, | ||||
| 				JVMCommonSpec: JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: JVMStressAction, | ||||
| 				JVMStressSpec: JVMStressSpec{ | ||||
| 					CPUCount: 1, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"", | ||||
| 		}, | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ import ( | |||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strings" | ||||
| 	"text/template" | ||||
|  | @ -29,30 +30,6 @@ import ( | |||
| 	"github.com/chaos-mesh/chaosd/pkg/core" | ||||
| ) | ||||
| 
 | ||||
| const ruleTemplate = ` | ||||
| RULE {{.Name}} | ||||
| CLASS {{.Class}} | ||||
| METHOD {{.Method}} | ||||
| AT ENTRY | ||||
| IF true | ||||
| DO  | ||||
| 	{{.Do}}; | ||||
| ENDRULE | ||||
| ` | ||||
| 
 | ||||
| const stressRuleTemplate = ` | ||||
| RULE {{.Name}} | ||||
| STRESS {{.StressType}} | ||||
| {{.StressValueName}} {{.StressValue}} | ||||
| ENDRULE | ||||
| ` | ||||
| 
 | ||||
| const gcRuleTemplate = ` | ||||
| RULE {{.Name}} | ||||
| GC | ||||
| ENDRULE | ||||
| ` | ||||
| 
 | ||||
| type jvmAttack struct{} | ||||
| 
 | ||||
| var JVMAttack AttackType = jvmAttack{} | ||||
|  | @ -83,13 +60,25 @@ func (j jvmAttack) Attack(options core.AttackConfig, env Environment) (err error | |||
| 		log.Debug(string(output), zap.Error(err)) | ||||
| 	} | ||||
| 
 | ||||
| 	// submit helper jar
 | ||||
| 	bmSubmitCmd := fmt.Sprintf(bmSubmitCommand, attack.Port, "b", fmt.Sprintf("%s/lib/byteman-helper.jar", os.Getenv("BYTEMAN_HOME"))) | ||||
| 	cmd = exec.Command("bash", "-c", bmSubmitCmd) | ||||
| 	output, err = cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
| 		log.Error(string(output), zap.Error(err)) | ||||
| 		return err | ||||
| 	} | ||||
| 	if len(output) > 0 { | ||||
| 		log.Info("submit helper", zap.String("output", string(output))) | ||||
| 	} | ||||
| 
 | ||||
| 	// submit rules
 | ||||
| 	ruleFile, err := j.generateRuleFile(attack) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	bmSubmitCmd := fmt.Sprintf(bmSubmitCommand, attack.Port, "l", ruleFile) | ||||
| 	bmSubmitCmd = fmt.Sprintf(bmSubmitCommand, attack.Port, "l", ruleFile) | ||||
| 	cmd = exec.Command("bash", "-c", bmSubmitCmd) | ||||
| 	output, err = cmd.CombinedOutput() | ||||
| 	if err != nil { | ||||
|  | @ -127,49 +116,11 @@ func (j jvmAttack) generateRuleFile(attack *core.JVMCommand) (string, error) { | |||
| 		return attack.RuleFile, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if len(attack.Do) == 0 { | ||||
| 		switch attack.Action { | ||||
| 		case core.JVMLatencyAction: | ||||
| 			attack.Do = fmt.Sprintf("Thread.sleep(%d)", attack.LatencyDuration) | ||||
| 		case core.JVMExceptionAction: | ||||
| 			attack.Do = fmt.Sprintf("throw new %s", attack.ThrowException) | ||||
| 		case core.JVMReturnAction: | ||||
| 			attack.Do = fmt.Sprintf("return %s", attack.ReturnValue) | ||||
| 		case core.JVMStressAction: | ||||
| 			if attack.CPUCount > 0 { | ||||
| 				attack.StressType = "CPU" | ||||
| 				attack.StressValueName = "CPUCOUNT" | ||||
| 				attack.StressValue = fmt.Sprintf("%d", attack.CPUCount) | ||||
| 			} else { | ||||
| 				attack.StressType = "MEMORY" | ||||
| 				attack.StressValueName = "MEMORYTYPE" | ||||
| 				attack.StressValue = attack.MemoryType | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	buf := new(bytes.Buffer) | ||||
| 	var t *template.Template | ||||
| 	switch attack.Action { | ||||
| 	case core.JVMStressAction: | ||||
| 		t = template.Must(template.New("byteman rule").Parse(stressRuleTemplate)) | ||||
| 	case core.JVMExceptionAction, core.JVMLatencyAction, core.JVMReturnAction: | ||||
| 		t = template.Must(template.New("byteman rule").Parse(ruleTemplate)) | ||||
| 	case core.JVMGCAction: | ||||
| 		t = template.Must(template.New("byteman rule").Parse(gcRuleTemplate)) | ||||
| 	default: | ||||
| 		return "", errors.Errorf("jvm action %s not supported", attack.Action) | ||||
| 	} | ||||
| 	if t == nil { | ||||
| 		return "", errors.Errorf("parse byeman rule template failed") | ||||
| 	} | ||||
| 	err = t.Execute(buf, attack) | ||||
| 	attack.RuleData, err = generateRuleData(attack) | ||||
| 	if err != nil { | ||||
| 		log.Error("executing template", zap.Error(err)) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	attack.RuleData = buf.String() | ||||
| 
 | ||||
| 	filename, err := writeDataIntoFile(attack.RuleData, "rule.btm") | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
|  | @ -204,6 +155,64 @@ func (j jvmAttack) Recover(exp core.Experiment, env Environment) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func generateRuleData(attack *core.JVMCommand) (string, error) { | ||||
| 	bytemanTemplateSpec := core.BytemanTemplateSpec{ | ||||
| 		Name:   attack.Name, | ||||
| 		Class:  attack.Class, | ||||
| 		Method: attack.Method, | ||||
| 	} | ||||
| 
 | ||||
| 	switch attack.Action { | ||||
| 	case core.JVMLatencyAction: | ||||
| 		bytemanTemplateSpec.Do = fmt.Sprintf("Thread.sleep(%d)", attack.LatencyDuration) | ||||
| 	case core.JVMExceptionAction: | ||||
| 		bytemanTemplateSpec.Do = fmt.Sprintf("throw new %s", attack.ThrowException) | ||||
| 	case core.JVMReturnAction: | ||||
| 		bytemanTemplateSpec.Do = fmt.Sprintf("return %s", attack.ReturnValue) | ||||
| 	case core.JVMStressAction: | ||||
| 		bytemanTemplateSpec.Helper = core.StressHelper | ||||
| 		bytemanTemplateSpec.Class = core.TriggerClass | ||||
| 		bytemanTemplateSpec.Method = core.TriggerMethod | ||||
| 		// the bind and condition is useless, only used for fill the template
 | ||||
| 		bytemanTemplateSpec.Bind = "flag:boolean=true" | ||||
| 		bytemanTemplateSpec.Condition = "true" | ||||
| 		if attack.CPUCount > 0 { | ||||
| 			bytemanTemplateSpec.Do = fmt.Sprintf("injectCPUStress(\"%s\", %d)", attack.Name, attack.CPUCount) | ||||
| 		} else { | ||||
| 			bytemanTemplateSpec.Do = fmt.Sprintf("injectMemStress(\"%s\", %s)", attack.Name, attack.MemoryType) | ||||
| 		} | ||||
| 	case core.JVMGCAction: | ||||
| 		bytemanTemplateSpec.Helper = core.GCHelper | ||||
| 		bytemanTemplateSpec.Class = core.TriggerClass | ||||
| 		bytemanTemplateSpec.Method = core.TriggerMethod | ||||
| 		// the bind and condition is useless, only used for fill the template
 | ||||
| 		bytemanTemplateSpec.Bind = "flag:boolean=true" | ||||
| 		bytemanTemplateSpec.Condition = "true" | ||||
| 		bytemanTemplateSpec.Do = "gc()" | ||||
| 	} | ||||
| 
 | ||||
| 	buf := new(bytes.Buffer) | ||||
| 	var t *template.Template | ||||
| 	switch attack.Action { | ||||
| 	case core.JVMStressAction, core.JVMGCAction: | ||||
| 		t = template.Must(template.New("byteman rule").Parse(core.CompleteRuleTemplate)) | ||||
| 	case core.JVMExceptionAction, core.JVMLatencyAction, core.JVMReturnAction: | ||||
| 		t = template.Must(template.New("byteman rule").Parse(core.SimpleRuleTemplate)) | ||||
| 	default: | ||||
| 		return "", errors.Errorf("jvm action %s not supported", attack.Action) | ||||
| 	} | ||||
| 	if t == nil { | ||||
| 		return "", errors.Errorf("parse byeman rule template failed") | ||||
| 	} | ||||
| 	err := t.Execute(buf, bytemanTemplateSpec) | ||||
| 	if err != nil { | ||||
| 		log.Error("executing template", zap.Error(err)) | ||||
| 		return "", err | ||||
| 	} | ||||
| 
 | ||||
| 	return buf.String(), nil | ||||
| } | ||||
| 
 | ||||
| func writeDataIntoFile(data string, filename string) (string, error) { | ||||
| 	tmpfile, err := ioutil.TempFile("", filename) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -0,0 +1,119 @@ | |||
| // Copyright 2021 Chaos Mesh Authors.
 | ||||
| //
 | ||||
| // 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,
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| package chaosd | ||||
| 
 | ||||
| import ( | ||||
| 	"testing" | ||||
| 
 | ||||
| 	. "github.com/onsi/gomega" | ||||
| 
 | ||||
| 	"github.com/chaos-mesh/chaosd/pkg/core" | ||||
| ) | ||||
| 
 | ||||
| func TestGenerateRuleData(t *testing.T) { | ||||
| 	g := NewGomegaWithT(t) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		cmd      *core.JVMCommand | ||||
| 		ruleData string | ||||
| 	}{ | ||||
| 		{ | ||||
| 			&core.JVMCommand{ | ||||
| 				Name: "test", | ||||
| 				JVMCommonSpec: core.JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: core.JVMExceptionAction, | ||||
| 				JVMClassMethodSpec: core.JVMClassMethodSpec{ | ||||
| 					Class:  "testClass", | ||||
| 					Method: "testMethod", | ||||
| 				}, | ||||
| 				ThrowException: "java.io.IOException(\"BOOM\")", | ||||
| 			}, | ||||
| 			"\nRULE test\nCLASS testClass\nMETHOD testMethod\nAT ENTRY\nIF true\nDO\n\tthrow new java.io.IOException(\"BOOM\");\nENDRULE\n", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&core.JVMCommand{ | ||||
| 				Name: "test", | ||||
| 				JVMCommonSpec: core.JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: core.JVMReturnAction, | ||||
| 				JVMClassMethodSpec: core.JVMClassMethodSpec{ | ||||
| 					Class:  "testClass", | ||||
| 					Method: "testMethod", | ||||
| 				}, | ||||
| 				ReturnValue: "\"test\"", | ||||
| 			}, | ||||
| 			"\nRULE test\nCLASS testClass\nMETHOD testMethod\nAT ENTRY\nIF true\nDO\n\treturn \"test\";\nENDRULE\n", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&core.JVMCommand{ | ||||
| 				Name: "test", | ||||
| 				JVMCommonSpec: core.JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: core.JVMLatencyAction, | ||||
| 				JVMClassMethodSpec: core.JVMClassMethodSpec{ | ||||
| 					Class:  "testClass", | ||||
| 					Method: "testMethod", | ||||
| 				}, | ||||
| 				LatencyDuration: 5000, | ||||
| 			}, | ||||
| 			"\nRULE test\nCLASS testClass\nMETHOD testMethod\nAT ENTRY\nIF true\nDO\n\tThread.sleep(5000);\nENDRULE\n", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&core.JVMCommand{ | ||||
| 				Name: "test", | ||||
| 				JVMCommonSpec: core.JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: core.JVMStressAction, | ||||
| 				JVMStressSpec: core.JVMStressSpec{ | ||||
| 					CPUCount: 1, | ||||
| 				}, | ||||
| 			}, | ||||
| 			"\nRULE test\nCLASS org.chaos_mesh.chaos_agent.TriggerThread\nMETHOD triggerFunc\nHELPER org.chaos_mesh.byteman.helper.StressHelper\nAT ENTRY\nBIND flag:boolean=true;\nIF true\nDO\n\tinjectCPUStress(\"test\", 1);\nENDRULE\n", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&core.JVMCommand{ | ||||
| 				Name: "test", | ||||
| 				JVMCommonSpec: core.JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: core.JVMStressAction, | ||||
| 				JVMStressSpec: core.JVMStressSpec{ | ||||
| 					MemoryType: "heap", | ||||
| 				}, | ||||
| 			}, | ||||
| 			"\nRULE test\nCLASS org.chaos_mesh.chaos_agent.TriggerThread\nMETHOD triggerFunc\nHELPER org.chaos_mesh.byteman.helper.StressHelper\nAT ENTRY\nBIND flag:boolean=true;\nIF true\nDO\n\tinjectMemStress(\"test\", heap);\nENDRULE\n", | ||||
| 		}, | ||||
| 		{ | ||||
| 			&core.JVMCommand{ | ||||
| 				Name: "test", | ||||
| 				JVMCommonSpec: core.JVMCommonSpec{ | ||||
| 					Pid: 1234, | ||||
| 				}, | ||||
| 				Action: core.JVMGCAction, | ||||
| 			}, | ||||
| 			"\nRULE test\nCLASS org.chaos_mesh.chaos_agent.TriggerThread\nMETHOD triggerFunc\nHELPER org.chaos_mesh.byteman.helper.GCHelper\nAT ENTRY\nBIND flag:boolean=true;\nIF true\nDO\n\tgc();\nENDRULE\n", | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	for _, testCase := range testCases { | ||||
| 		ruleData, err := generateRuleData(testCase.cmd) | ||||
| 		g.Expect(err).ShouldNot(HaveOccurred()) | ||||
| 		g.Expect(ruleData).Should(Equal(testCase.ruleData)) | ||||
| 	} | ||||
| } | ||||
|  | @ -13,15 +13,28 @@ | |||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| 
 | ||||
| set -u | ||||
| set -eu | ||||
| 
 | ||||
| cur=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) | ||||
| cd $cur | ||||
| 
 | ||||
| bin_path=../../../bin | ||||
| 
 | ||||
| echo "download && build && run Java example program" | ||||
| git clone https://github.com/WangXiangUSTC/byteman-example.git | ||||
| echo "download byteman example" | ||||
| if [[ ! (-e byteman-example) ]]; then | ||||
|     git clone https://github.com/WangXiangUSTC/byteman-example.git | ||||
| fi | ||||
| 
 | ||||
| echo "download byteman && set environment variable" | ||||
| byteman_dir="byteman-chaos-mesh-download-v4.0.18-0.9" | ||||
| if [[ ! (-e ${byteman_dir}.tar.gz) ]]; then | ||||
|     curl -fsSL -o ${byteman_dir}.tar.gz https://mirrors.chaos-mesh.org/${byteman_dir}.tar.gz | ||||
|     tar zxvf ${byteman_dir}.tar.gz | ||||
| fi | ||||
| export BYTEMAN_HOME=$cur/${byteman_dir} | ||||
| export PATH=$PATH:${BYTEMAN_HOME}/bin | ||||
| 
 | ||||
| echo "build && run Java example program helloworld" | ||||
| cd byteman-example/example.helloworld | ||||
| javac HelloWorld/Main.java | ||||
| jar cfme HelloWorld.jar Manifest.txt HelloWorld.Main HelloWorld/Main.class | ||||
|  | @ -33,19 +46,14 @@ cat helloworld.log | |||
| # TODO: get the PID more accurately | ||||
| pid=`pgrep -n java` | ||||
| 
 | ||||
| echo "download byteman && set environment variable" | ||||
| curl -fsSL -o chaosd-byteman-download.tar.gz https://mirrors.chaos-mesh.org/jvm/chaosd-byteman-download.tar.gz | ||||
| tar zxvf chaosd-byteman-download.tar.gz | ||||
| export BYTEMAN_HOME=$cur/chaosd-byteman-download | ||||
| export PATH=$PATH:${BYTEMAN_HOME}/bin | ||||
| 
 | ||||
| echo "run chaosd to inject failure into JVM, and check" | ||||
| $bin_path/chaosd attack jvm install --port 9288 --pid $pid | ||||
| 
 | ||||
| $bin_path/chaosd attack jvm submit return --class Main --method getnum --port 9288  --value 99999 | ||||
| $bin_path/chaosd attack jvm return --class Main --method getnum --port 9288  --value 99999 --pid $pid | ||||
| sleep 1 | ||||
| check_contains "99999" helloworld.log | ||||
| 
 | ||||
| $bin_path/chaosd attack jvm submit exception  --class Main --method sayhello --port 9288 --exception 'java.io.IOException("BOOM")' | ||||
| $bin_path/chaosd attack jvm exception  --class Main --method sayhello --port 9288 --exception 'java.io.IOException("BOOM")' --pid $pid | ||||
| sleep 1 | ||||
| check_contains "BOOM" helloworld.log | ||||
| 
 | ||||
| # TODO: add test for latency, stress and gc | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue