better demo for omni methods

This commit is contained in:
金戟 2021-03-22 00:41:19 +08:00
parent b062dbc592
commit 9064f7a582
27 changed files with 208 additions and 1074 deletions

View File

@ -0,0 +1,40 @@
package com.alibaba.demo.basic.model.omni;
public class Child {
// ---------- 内部成员字段 ----------
private GrandChild grandChild;
private InnerChild subChild;
/* ---------------------------------------
以下Getters/Setters方法仅为便于功能演示而添加
并非OmniConstructor或OmniAccessor功能所需
--------------------------------------- */
public GrandChild getGrandChild() {
return grandChild;
}
public void setGrandChild(GrandChild grandChild) {
this.grandChild = grandChild;
}
public InnerChild getSubChild() {
return subChild;
}
public void setSubChild(InnerChild subChild) {
this.subChild = subChild;
}
/**
* 这是一个私有内部类
* An private inner class
*/
private static class InnerChild {
private String secret;
}
}

View File

@ -1,158 +0,0 @@
package com.alibaba.demo.basic.model.omni;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Container {
// ---------- Member fields ----------
private List<String> args = new ArrayList();
private String command;
private Map<String, String> env = new HashMap<>();
private String image;
private String imagePullPolicy;
private Probe livenessProbe;
private String name;
private List<ContainerPort> ports = new ArrayList();
private Probe readinessProbe;
private Probe startupProbe;
private Boolean stdin;
private Boolean stdinOnce;
private String terminationMessagePath;
private String terminationMessagePolicy;
private Boolean tty;
private String workingDir;
// ---------- Getters and Setters ----------
public List<String> getArgs() {
return args;
}
public void setArgs(List<String> args) {
this.args = args;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public Map<String, String> getEnv() {
return env;
}
public void setEnv(Map<String, String> env) {
this.env = env;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getImagePullPolicy() {
return imagePullPolicy;
}
public void setImagePullPolicy(String imagePullPolicy) {
this.imagePullPolicy = imagePullPolicy;
}
public Probe getLivenessProbe() {
return livenessProbe;
}
public void setLivenessProbe(Probe livenessProbe) {
this.livenessProbe = livenessProbe;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ContainerPort> getPorts() {
return ports;
}
public void setPorts(List<ContainerPort> ports) {
this.ports = ports;
}
public Probe getReadinessProbe() {
return readinessProbe;
}
public void setReadinessProbe(Probe readinessProbe) {
this.readinessProbe = readinessProbe;
}
public Probe getStartupProbe() {
return startupProbe;
}
public void setStartupProbe(Probe startupProbe) {
this.startupProbe = startupProbe;
}
public Boolean getStdin() {
return stdin;
}
public void setStdin(Boolean stdin) {
this.stdin = stdin;
}
public Boolean getStdinOnce() {
return stdinOnce;
}
public void setStdinOnce(Boolean stdinOnce) {
this.stdinOnce = stdinOnce;
}
public String getTerminationMessagePath() {
return terminationMessagePath;
}
public void setTerminationMessagePath(String terminationMessagePath) {
this.terminationMessagePath = terminationMessagePath;
}
public String getTerminationMessagePolicy() {
return terminationMessagePolicy;
}
public void setTerminationMessagePolicy(String terminationMessagePolicy) {
this.terminationMessagePolicy = terminationMessagePolicy;
}
public Boolean getTty() {
return tty;
}
public void setTty(Boolean tty) {
this.tty = tty;
}
public String getWorkingDir() {
return workingDir;
}
public void setWorkingDir(String workingDir) {
this.workingDir = workingDir;
}
}

View File

@ -1,54 +0,0 @@
package com.alibaba.demo.basic.model.omni;
public class ContainerPort {
// ---------- Member fields ----------
private Integer containerPort;
private String hostIP;
private Integer hostPort;
private String name;
private String protocol;
// ---------- Getters and Setters ----------
public Integer getContainerPort() {
return containerPort;
}
public void setContainerPort(Integer containerPort) {
this.containerPort = containerPort;
}
public String getHostIP() {
return hostIP;
}
public void setHostIP(String hostIP) {
this.hostIP = hostIP;
}
public Integer getHostPort() {
return hostPort;
}
public void setHostPort(Integer hostPort) {
this.hostPort = hostPort;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
}

View File

@ -1,18 +0,0 @@
package com.alibaba.demo.basic.model.omni;
public class ExecAction {
// ---------- Member fields ----------
private String command;
// ---------- Getters and Setters ----------
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
}

View File

@ -0,0 +1,31 @@
package com.alibaba.demo.basic.model.omni;
public class GrandChild {
// ---------- 内部成员字段 ----------
private int value;
private String content;
/* ---------------------------------------
以下Getters/Setters方法仅为便于功能演示而添加
并非OmniConstructor或OmniAccessor功能所需
--------------------------------------- */
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@ -1,139 +0,0 @@
package com.alibaba.demo.basic.model.omni;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ObjectMeta {
// ---------- Member fields ----------
private Map<String, String> annotations;
private String clusterName;
private String creationTimestamp;
private Long deletionGracePeriodSeconds;
private String deletionTimestamp;
private List<String> finalizers = new ArrayList();
private String generateName;
private Long generation;
private Map<String, String> labels;
private String name;
private String namespace;
private String resourceVersion;
private String selfLink;
private String uid;
// ---------- Getters and Setters ----------
public Map<String, String> getAnnotations() {
return annotations;
}
public void setAnnotations(Map<String, String> annotations) {
this.annotations = annotations;
}
public String getClusterName() {
return clusterName;
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
public String getCreationTimestamp() {
return creationTimestamp;
}
public void setCreationTimestamp(String creationTimestamp) {
this.creationTimestamp = creationTimestamp;
}
public Long getDeletionGracePeriodSeconds() {
return deletionGracePeriodSeconds;
}
public void setDeletionGracePeriodSeconds(Long deletionGracePeriodSeconds) {
this.deletionGracePeriodSeconds = deletionGracePeriodSeconds;
}
public String getDeletionTimestamp() {
return deletionTimestamp;
}
public void setDeletionTimestamp(String deletionTimestamp) {
this.deletionTimestamp = deletionTimestamp;
}
public List<String> getFinalizers() {
return finalizers;
}
public void setFinalizers(List<String> finalizers) {
this.finalizers = finalizers;
}
public String getGenerateName() {
return generateName;
}
public void setGenerateName(String generateName) {
this.generateName = generateName;
}
public Long getGeneration() {
return generation;
}
public void setGeneration(Long generation) {
this.generation = generation;
}
public Map<String, String> getLabels() {
return labels;
}
public void setLabels(Map<String, String> labels) {
this.labels = labels;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getResourceVersion() {
return resourceVersion;
}
public void setResourceVersion(String resourceVersion) {
this.resourceVersion = resourceVersion;
}
public String getSelfLink() {
return selfLink;
}
public void setSelfLink(String selfLink) {
this.selfLink = selfLink;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
}

View File

@ -0,0 +1,32 @@
package com.alibaba.demo.basic.model.omni;
public class Parent {
// ---------- 内部成员字段 ----------
private Child child;
private Child[] children;
/* ---------------------------------------
以下Getters/Setters方法仅为便于功能演示而添加
并非OmniConstructor或OmniAccessor功能所需
--------------------------------------- */
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
public Child[] getChildren() {
return children;
}
public void setChildren(Child[] children) {
this.children = children;
}
}

View File

@ -1,58 +0,0 @@
package com.alibaba.demo.basic.model.omni;
/**
* 这是一个简化了的Kubernetes Pod模型
* This is a simplified kubernetes pod model
*/
public class Pod {
// ---------- Member fields ----------
private String apiVersion = "v1";
private String kind = "Pod";
private ObjectMeta metadata;
private PodSpec spec;
private PodStatus status;
// ---------- Getters and Setters ----------
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
public ObjectMeta getMetadata() {
return metadata;
}
public void setMetadata(ObjectMeta metadata) {
this.metadata = metadata;
}
public PodSpec getSpec() {
return spec;
}
public void setSpec(PodSpec spec) {
this.spec = spec;
}
public PodStatus getStatus() {
return status;
}
public void setStatus(PodStatus status) {
this.status = status;
}
}

View File

@ -1,227 +0,0 @@
package com.alibaba.demo.basic.model.omni;
import java.util.Map;
public class PodSpec {
// ---------- Member fields ----------
private Long activeDeadlineSeconds;
private Boolean automountServiceAccountToken;
private Container[] containers;
private String dnsPolicy;
private Boolean enableServiceLinks;
private Boolean hostIPC;
private Boolean hostNetwork;
private Boolean hostPID;
private String hostname;
private Container[] initContainers;
private String nodeName;
private Map<String, String> nodeSelector;
private String preemptionPolicy;
private Integer priority;
private String priorityClassName;
private String restartPolicy;
private String runtimeClassName;
private String schedulerName;
private String serviceAccount;
private String serviceAccountName;
private Boolean setHostnameAsFQDN;
private Boolean shareProcessNamespace;
private String subdomain;
private Long terminationGracePeriodSeconds;
// ---------- Getters and Setters ----------
public Long getActiveDeadlineSeconds() {
return activeDeadlineSeconds;
}
public void setActiveDeadlineSeconds(Long activeDeadlineSeconds) {
this.activeDeadlineSeconds = activeDeadlineSeconds;
}
public Boolean getAutomountServiceAccountToken() {
return automountServiceAccountToken;
}
public void setAutomountServiceAccountToken(Boolean automountServiceAccountToken) {
this.automountServiceAccountToken = automountServiceAccountToken;
}
public Container[] getContainers() {
return containers;
}
public void setContainers(Container[] containers) {
this.containers = containers;
}
public String getDnsPolicy() {
return dnsPolicy;
}
public void setDnsPolicy(String dnsPolicy) {
this.dnsPolicy = dnsPolicy;
}
public Boolean getEnableServiceLinks() {
return enableServiceLinks;
}
public void setEnableServiceLinks(Boolean enableServiceLinks) {
this.enableServiceLinks = enableServiceLinks;
}
public Boolean getHostIPC() {
return hostIPC;
}
public void setHostIPC(Boolean hostIPC) {
this.hostIPC = hostIPC;
}
public Boolean getHostNetwork() {
return hostNetwork;
}
public void setHostNetwork(Boolean hostNetwork) {
this.hostNetwork = hostNetwork;
}
public Boolean getHostPID() {
return hostPID;
}
public void setHostPID(Boolean hostPID) {
this.hostPID = hostPID;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public Container[] getInitContainers() {
return initContainers;
}
public void setInitContainers(Container[] initContainers) {
this.initContainers = initContainers;
}
public String getNodeName() {
return nodeName;
}
public void setNodeName(String nodeName) {
this.nodeName = nodeName;
}
public Map<String, String> getNodeSelector() {
return nodeSelector;
}
public void setNodeSelector(Map<String, String> nodeSelector) {
this.nodeSelector = nodeSelector;
}
public String getPreemptionPolicy() {
return preemptionPolicy;
}
public void setPreemptionPolicy(String preemptionPolicy) {
this.preemptionPolicy = preemptionPolicy;
}
public Integer getPriority() {
return priority;
}
public void setPriority(Integer priority) {
this.priority = priority;
}
public String getPriorityClassName() {
return priorityClassName;
}
public void setPriorityClassName(String priorityClassName) {
this.priorityClassName = priorityClassName;
}
public String getRestartPolicy() {
return restartPolicy;
}
public void setRestartPolicy(String restartPolicy) {
this.restartPolicy = restartPolicy;
}
public String getRuntimeClassName() {
return runtimeClassName;
}
public void setRuntimeClassName(String runtimeClassName) {
this.runtimeClassName = runtimeClassName;
}
public String getSchedulerName() {
return schedulerName;
}
public void setSchedulerName(String schedulerName) {
this.schedulerName = schedulerName;
}
public String getServiceAccount() {
return serviceAccount;
}
public void setServiceAccount(String serviceAccount) {
this.serviceAccount = serviceAccount;
}
public String getServiceAccountName() {
return serviceAccountName;
}
public void setServiceAccountName(String serviceAccountName) {
this.serviceAccountName = serviceAccountName;
}
public Boolean getSetHostnameAsFQDN() {
return setHostnameAsFQDN;
}
public void setSetHostnameAsFQDN(Boolean setHostnameAsFQDN) {
this.setHostnameAsFQDN = setHostnameAsFQDN;
}
public Boolean getShareProcessNamespace() {
return shareProcessNamespace;
}
public void setShareProcessNamespace(Boolean shareProcessNamespace) {
this.shareProcessNamespace = shareProcessNamespace;
}
public String getSubdomain() {
return subdomain;
}
public void setSubdomain(String subdomain) {
this.subdomain = subdomain;
}
public Long getTerminationGracePeriodSeconds() {
return terminationGracePeriodSeconds;
}
public void setTerminationGracePeriodSeconds(Long terminationGracePeriodSeconds) {
this.terminationGracePeriodSeconds = terminationGracePeriodSeconds;
}
}

View File

@ -1,22 +0,0 @@
package com.alibaba.demo.basic.model.omni;
public enum PodStatus {
/**
* waiting
*/
WAITING("waiting"),
/**
* running
*/
RUNNING("running"),
/**
* terminated
*/
TERMINATED("terminated");
PodStatus(String status) {}
}

View File

@ -1,63 +0,0 @@
package com.alibaba.demo.basic.model.omni;
public class Probe {
// ---------- Member fields ----------
private ExecAction exec;
private Integer failureThreshold;
private Integer initialDelaySeconds;
private Integer periodSeconds;
private Integer successThreshold;
private Integer timeoutSeconds;
// ---------- Getters and Setters ----------
public ExecAction getExec() {
return exec;
}
public void setExec(ExecAction exec) {
this.exec = exec;
}
public Integer getFailureThreshold() {
return failureThreshold;
}
public void setFailureThreshold(Integer failureThreshold) {
this.failureThreshold = failureThreshold;
}
public Integer getInitialDelaySeconds() {
return initialDelaySeconds;
}
public void setInitialDelaySeconds(Integer initialDelaySeconds) {
this.initialDelaySeconds = initialDelaySeconds;
}
public Integer getPeriodSeconds() {
return periodSeconds;
}
public void setPeriodSeconds(Integer periodSeconds) {
this.periodSeconds = periodSeconds;
}
public Integer getSuccessThreshold() {
return successThreshold;
}
public void setSuccessThreshold(Integer successThreshold) {
this.successThreshold = successThreshold;
}
public Integer getTimeoutSeconds() {
return timeoutSeconds;
}
public void setTimeoutSeconds(Integer timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
}
}

View File

@ -0,0 +1,91 @@
package com.alibaba.demo.basic;
import com.alibaba.demo.basic.model.omni.Child;
import com.alibaba.demo.basic.model.omni.Parent;
import com.alibaba.testable.core.tool.OmniAccessor;
import com.alibaba.testable.core.tool.OmniConstructor;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* 演示快速创建任意对象和使用路径访问成员
* Demonstrate quick object construction and access members by path
*/
class DemoOmniMethodsTest {
@Test
void should_construct_any_class() {
Parent parent = OmniConstructor.newInstance(Parent.class);
// 任意深度的子孙成员对象都不为空
assertNotNull(parent.getChild().getGrandChild().getContent());
// 所有基础类型初始化为默认数值
assertEquals(0, parent.getChild().getGrandChild().getValue());
assertEquals("", parent.getChild().getGrandChild().getContent());
// 所有数组类型初始化为空数组
assertEquals(0, parent.getChildren().length);
}
@Test
void should_get_any_member() {
Parent parent = OmniConstructor.newInstance(Parent.class);
parent.setChildren(OmniConstructor.newArray(Child.class, 3));
parent.getChild().getGrandChild().setContent("from child");
parent.getChildren()[0].getGrandChild().setContent("from 1st children");
parent.getChildren()[1].getGrandChild().setContent("from 2nd children");
parent.getChildren()[2].getGrandChild().setContent("from 3rd children");
// 使用成员名称快速读取成员对象
List<String> contents = OmniAccessor.get(parent, "content");
assertEquals(4, contents.size());
assertEquals("from child", contents.get(0));
assertEquals("from 1st children", contents.get(1));
assertEquals("from 2nd children", contents.get(2));
assertEquals("from 3rd children", contents.get(3));
// 使用成员类型快速读取成员对象
contents = OmniAccessor.get(parent, "{Child}/{GrandChild}/content");
assertEquals(1, contents.size());
assertEquals("from child", contents.get(0));
// 使用带下标的路径读取成员对象
assertEquals("from 2nd children", OmniAccessor.getFirst(parent, "children[1]/{GrandChild}/content"));
assertEquals("from 3rd children", OmniAccessor.getFirst(parent, "{Child[]}[2]/{GrandChild}/content"));
// 使用模糊路径快速读取成员对象
assertEquals("from 1st children", OmniAccessor.getFirst(parent, "{C*[]}[0]/*/con*t"));
}
@Test
void should_set_any_member() {
Parent parent = OmniConstructor.newInstance(Parent.class);
parent.setChildren(OmniConstructor.newArray(Child.class, 3));
// 使用指定路径快速给成员对象赋值
OmniAccessor.set(parent, "child/grandChild/content", "demo child");
assertEquals("demo child", parent.getChild().getGrandChild().getContent());
// 使用带下标的路径给成员对象赋值
OmniAccessor.set(parent, "children[1]/grandChild/content", "demo children[1]");
assertEquals("demo children[1]", parent.getChildren()[1].getGrandChild().getContent());
// 使用模糊路径批量给成员对象赋值
OmniAccessor.set(parent, "child*/*/content", "demo in batch");
assertEquals("demo in batch", parent.getChild().getGrandChild().getContent());
assertEquals("demo in batch", parent.getChildren()[0].getGrandChild().getContent());
assertEquals("demo in batch", parent.getChildren()[1].getGrandChild().getContent());
assertEquals("demo in batch", parent.getChildren()[2].getGrandChild().getContent());
// 读写私有内部类类型的成员注意使用类型名引用类别类时无需带外部类名
assertEquals("", OmniAccessor.getFirst(parent, "subChild/secret"));
OmniAccessor.set(parent, "{InnerChild}/secret", "inner-class secret");
assertEquals("inner-class secret", OmniAccessor.getFirst(parent, "subChild/secret"));
}
}

View File

@ -13,7 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
* 演示使用`PrivateAccessor`工具类访问私有成员
* Demonstrate access private member via `PrivateAccessor` class
*/
class PrivateAccessorTest {
class DemoPrivateAccessorTest {
private DemoPrivateAccess demoPrivateAccess = new DemoPrivateAccess();

View File

@ -14,7 +14,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
* Demonstrate access private member via `@EnablePrivateAccess` annotation
*/
@EnablePrivateAccess(srcClass = DemoPrivateAccess.class)
class PrivateProcessorTest {
class DemoPrivateProcessorTest {
private DemoPrivateAccess demoPrivateAccess = new DemoPrivateAccess();

View File

@ -1,99 +0,0 @@
package com.alibaba.demo.basic;
import com.alibaba.demo.basic.model.omni.*;
import com.alibaba.testable.core.tool.OmniAccessor;
import com.alibaba.testable.core.tool.OmniConstructor;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* 演示快速创建任意对象和使用路径访问成员
* Demonstrate quick object construction and access members by path
*/
class OmniConstructorTest {
@Test
void should_construct_any_class() {
Pod pod = OmniConstructor.newInstance(Pod.class);
Container container = OmniConstructor.newInstance(Container.class);
// 所有基础类型初始化为默认数值
assertEquals(0L, pod.getSpec().getActiveDeadlineSeconds());
// 所有枚举类型初始化为第一个可选值
assertEquals(PodStatus.WAITING, pod.getStatus());
// 所有数组类型初始化为空数组
assertEquals(0, pod.getSpec().getContainers().length);
// 任意深度的子孙成员对象都会被初始化
assertEquals("", container.getReadinessProbe().getExec().getCommand());
}
@Test
void should_get_any_member() {
Pod pod = OmniConstructor.newInstance(Pod.class);
pod.getSpec().setContainers( OmniConstructor.newArray(Container.class, 3) );
pod.getSpec().getContainers()[0].setCommand("container-cmd-1st");
pod.getSpec().getContainers()[0].getLivenessProbe().getExec().setCommand("liveness-cmd-1st");
pod.getSpec().getContainers()[0].getReadinessProbe().getExec().setCommand("readness-cmd-1st");
pod.getSpec().getContainers()[0].getStartupProbe().getExec().setCommand("startup-cmd-1st");
pod.getSpec().getContainers()[1].setCommand("container-cmd-2nd");
pod.getSpec().getContainers()[1].getLivenessProbe().getExec().setCommand("liveness-cmd-2nd");
pod.getSpec().getContainers()[1].getReadinessProbe().getExec().setCommand("readness-cmd-2nd");
pod.getSpec().getContainers()[1].getStartupProbe().getExec().setCommand("startup-cmd-2nd");
pod.getSpec().getContainers()[2].setCommand("container-cmd-3rd");
pod.getSpec().getContainers()[2].getLivenessProbe().getExec().setCommand("liveness-cmd-3rd");
pod.getSpec().getContainers()[2].getReadinessProbe().getExec().setCommand("readness-cmd-3rd");
pod.getSpec().getContainers()[2].getStartupProbe().getExec().setCommand("startup-cmd-3rd");
// 使用成员名快速读取成员变量
List<String> commands = OmniAccessor.get(pod, "command");
assertEquals(12, commands.size());
assertEquals("container-cmd-1st", commands.get(0));
assertEquals("liveness-cmd-1st", commands.get(3));
assertEquals("readness-cmd-1st", commands.get(6));
assertEquals("startup-cmd-1st", commands.get(9));
// 使用成员类型快速读取成员变量
List<Probe> probes = OmniAccessor.get(pod, "{Probe}");
assertEquals(9, probes.size());
assertEquals("liveness-cmd-1st", probes.get(0).getExec().getCommand());
assertEquals("readness-cmd-1st", probes.get(3).getExec().getCommand());
assertEquals("startup-cmd-1st", probes.get(6).getExec().getCommand());
// 使用模糊路径快速读取成员变量
List<String> startupCommands = OmniAccessor.get(pod, "startupProbe/*/command");
assertEquals(3, startupCommands.size());
assertEquals("startup-cmd-1st", startupCommands.get(0));
assertEquals("startup-cmd-2nd", startupCommands.get(1));
assertEquals("startup-cmd-3rd", startupCommands.get(2));
// 使用带下标的路径读取成员变量
List<Probe> firstStartupCommands = OmniAccessor.get(pod, "containers[0]/livenessProbe");
assertEquals(1, firstStartupCommands.size());
assertEquals("liveness-cmd-1st", firstStartupCommands.get(0).getExec().getCommand());
}
@Test
void should_set_any_member() {
Pod pod = OmniConstructor.newInstance(Pod.class);
pod.getSpec().setContainers( OmniConstructor.newArray(Container.class, 3) );
// 使用模糊路径批量给成员变量赋值
OmniAccessor.set(pod, "containers/command", "container-cmd");
OmniAccessor.set(pod, "{Probe}/*/command", "probe-cmd");
assertEquals("container-cmd", pod.getSpec().getContainers()[0].getCommand());
assertEquals("probe-cmd", pod.getSpec().getContainers()[1].getReadinessProbe().getExec().getCommand());
assertEquals("probe-cmd", pod.getSpec().getContainers()[2].getLivenessProbe().getExec().getCommand());
// 使用带下标的路径给成员变量赋值
OmniAccessor.set(pod, "containers[1]/*/*/command", "probe-cmd-2nd");
assertEquals("probe-cmd", pod.getSpec().getContainers()[0].getLivenessProbe().getExec().getCommand());
assertEquals("probe-cmd-2nd", pod.getSpec().getContainers()[1].getLivenessProbe().getExec().getCommand());
}
}

View File

@ -1,23 +0,0 @@
package com.alibaba.demo.basic.model.omni
import java.util.ArrayList
import java.util.HashMap
class Container {
var args: List<String?> = ArrayList()
var command: String? = null
var env: Map<String, String> = HashMap()
var image: String? = null
var imagePullPolicy: String? = null
var livenessProbe: Probe? = null
var name: String? = null
var ports: List<ContainerPort?> = ArrayList()
var readinessProbe: Probe? = null
var startupProbe: Probe? = null
var stdin: Boolean? = null
var stdinOnce: Boolean? = null
var terminationMessagePath: String? = null
var terminationMessagePolicy: String? = null
var tty: Boolean? = null
var workingDir: String? = null
}

View File

@ -1,9 +0,0 @@
package com.alibaba.demo.basic.model.omni
class ContainerPort {
var containerPort: Int? = null
var hostIP: String? = null
var hostPort: Int? = null
var name: String? = null
var protocol: String? = null
}

View File

@ -1,5 +0,0 @@
package com.alibaba.demo.basic.model.omni
class ExecAction {
var command: String? = null
}

View File

@ -1,20 +0,0 @@
package com.alibaba.demo.basic.model.omni
import java.util.ArrayList
class ObjectMeta {
var annotations: Map<String, String>? = null
var clusterName: String? = null
var creationTimestamp: String? = null
var deletionGracePeriodSeconds: Long? = null
var deletionTimestamp: String? = null
var finalizers: List<String?> = ArrayList<String?>()
var generateName: String? = null
var generation: Long? = null
var labels: Map<String, String>? = null
var name: String? = null
var namespace: String? = null
var resourceVersion: String? = null
var selfLink: String? = null
var uid: String? = null
}

View File

@ -1,13 +0,0 @@
package com.alibaba.demo.basic.model.omni
/**
* 这是一个简化了的Kubernetes Pod模型
* This is a simplified kubernetes pod model
*/
class Pod {
var apiVersion = "v1"
var kind = "Pod"
var metadata: ObjectMeta? = null
var spec: PodSpec? = null
var status: PodStatus? = null
}

View File

@ -1,28 +0,0 @@
package com.alibaba.demo.basic.model.omni
class PodSpec {
var activeDeadlineSeconds: Long? = null
var automountServiceAccountToken: Boolean? = null
var containers: Array<Container> = arrayOf()
var dnsPolicy: String? = null
var enableServiceLinks: Boolean? = null
var hostIPC: Boolean? = null
var hostNetwork: Boolean? = null
var hostPID: Boolean? = null
var hostname: String? = null
var initContainers: Array<Container> = arrayOf()
var nodeName: String? = null
var nodeSelector: Map<String, String>? = null
var preemptionPolicy: String? = null
var priority: Int? = null
var priorityClassName: String? = null
var restartPolicy: String? = null
var runtimeClassName: String? = null
var schedulerName: String? = null
var serviceAccount: String? = null
var serviceAccountName: String? = null
var setHostnameAsFQDN: Boolean? = null
var shareProcessNamespace: Boolean? = null
var subdomain: String? = null
var terminationGracePeriodSeconds: Long? = null
}

View File

@ -1,18 +0,0 @@
package com.alibaba.demo.basic.model.omni
enum class PodStatus(status: String) {
/**
* waiting
*/
WAITING("waiting"),
/**
* running
*/
RUNNING("running"),
/**
* terminated
*/
TERMINATED("terminated")
}

View File

@ -1,10 +0,0 @@
package com.alibaba.demo.basic.model.omni
class Probe {
var exec: ExecAction? = null
var failureThreshold: Int? = null
var initialDelaySeconds: Int? = null
var periodSeconds: Int? = null
var successThreshold: Int? = null
var timeoutSeconds: Int? = null
}

View File

@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test
* 演示私有成员访问功能
* Demonstrate private member access functionality
*/
internal class PrivateAccessorTest {
internal class DemoPrivateAccessorTest {
private val demoPrivateAccess = DemoPrivateAccess()

View File

@ -1,97 +0,0 @@
package com.alibaba.demo.basic
import com.alibaba.demo.basic.model.omni.Container
import com.alibaba.demo.basic.model.omni.Pod
import com.alibaba.demo.basic.model.omni.PodStatus
import com.alibaba.demo.basic.model.omni.Probe
import com.alibaba.testable.core.tool.OmniAccessor
import com.alibaba.testable.core.tool.OmniConstructor
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
/**
* 演示快速创建任意对象和使用路径访问成员
* Demonstrate quick object construction and access members by path
*/
internal class OmniConstructorTest {
@Test
fun should_construct_any_class() {
val pod = OmniConstructor.newInstance(Pod::class.java)
val container = OmniConstructor.newInstance(Container::class.java)
// 所有基础类型初始化为默认数值
Assertions.assertEquals(0L, pod.spec!!.activeDeadlineSeconds)
// 所有枚举类型初始化为第一个可选值
Assertions.assertEquals(PodStatus.WAITING, pod.status)
// 所有数组类型初始化为空数组
Assertions.assertEquals(0, pod.spec!!.containers.size)
// 任意深度的子孙成员对象都会被初始化
Assertions.assertEquals("", container.readinessProbe!!.exec!!.command)
}
@Test
fun should_get_any_member() {
val pod = OmniConstructor.newInstance(Pod::class.java)
pod.spec!!.containers = OmniConstructor.newArray(Container::class.java, 3)
pod.spec!!.containers[0].command = "container-cmd-1st"
pod.spec!!.containers[0].livenessProbe!!.exec!!.command = "liveness-cmd-1st"
pod.spec!!.containers[0].readinessProbe!!.exec!!.command = "readness-cmd-1st"
pod.spec!!.containers[0].startupProbe!!.exec!!.command = "startup-cmd-1st"
pod.spec!!.containers[1].command = "container-cmd-2nd"
pod.spec!!.containers[1].livenessProbe!!.exec!!.command = "liveness-cmd-2nd"
pod.spec!!.containers[1].readinessProbe!!.exec!!.command = "readness-cmd-2nd"
pod.spec!!.containers[1].startupProbe!!.exec!!.command = "startup-cmd-2nd"
pod.spec!!.containers[2].command = "container-cmd-3rd"
pod.spec!!.containers[2].livenessProbe!!.exec!!.command = "liveness-cmd-3rd"
pod.spec!!.containers[2].readinessProbe!!.exec!!.command = "readness-cmd-3rd"
pod.spec!!.containers[2].startupProbe!!.exec!!.command = "startup-cmd-3rd"
// 使用成员名快速读取成员变量
val commands = OmniAccessor.get<String>(pod, "command")
Assertions.assertEquals(12, commands.size)
Assertions.assertEquals("container-cmd-1st", commands[0])
Assertions.assertEquals("liveness-cmd-1st", commands[3])
Assertions.assertEquals("readness-cmd-1st", commands[6])
Assertions.assertEquals("startup-cmd-1st", commands[9])
// 使用成员类型快速读取成员变量
val probes: List<Probe> = OmniAccessor.get(pod, "{Probe}")
Assertions.assertEquals(9, probes.size)
Assertions.assertEquals("liveness-cmd-1st", probes[0].exec!!.command)
Assertions.assertEquals("readness-cmd-1st", probes[3].exec!!.command)
Assertions.assertEquals("startup-cmd-1st", probes[6].exec!!.command)
// 使用模糊路径快速读取成员变量
val startupCommands = OmniAccessor.get<String>(pod, "startupProbe/*/command")
Assertions.assertEquals(3, startupCommands.size)
Assertions.assertEquals("startup-cmd-1st", startupCommands[0])
Assertions.assertEquals("startup-cmd-2nd", startupCommands[1])
Assertions.assertEquals("startup-cmd-3rd", startupCommands[2])
// 使用带下标的路径读取成员变量
val firstStartupCommands: List<Probe> = OmniAccessor.get(pod, "containers[0]/livenessProbe")
Assertions.assertEquals(1, firstStartupCommands.size)
Assertions.assertEquals("liveness-cmd-1st", firstStartupCommands[0].exec!!.command)
}
@Test
fun should_set_any_member() {
val pod = OmniConstructor.newInstance(Pod::class.java)
pod.spec!!.containers = OmniConstructor.newArray(Container::class.java, 3)
// 使用模糊路径批量给成员变量赋值
OmniAccessor.set(pod, "containers/command", "container-cmd")
OmniAccessor.set(pod, "{Probe}/*/command", "probe-cmd")
Assertions.assertEquals("container-cmd", pod.spec!!.containers[0].command)
Assertions.assertEquals("probe-cmd", pod.spec!!.containers[1].readinessProbe!!.exec!!.command)
Assertions.assertEquals("probe-cmd", pod.spec!!.containers[2].livenessProbe!!.exec!!.command)
// 使用带下标的路径给成员变量赋值
OmniAccessor.set(pod, "containers[1]/*/*/command", "probe-cmd-2nd")
Assertions.assertEquals("probe-cmd", pod.spec!!.containers[0].livenessProbe!!.exec!!.command)
Assertions.assertEquals("probe-cmd-2nd", pod.spec!!.containers[1].livenessProbe!!.exec!!.command)
}
}

View File

@ -22,9 +22,10 @@ public class OmniAccessor {
private static final String THIS_REF_PREFIX = "this$";
private static final String PATTERN_PREFIX = ".*/";
private static final String REGEX_ANY_NAME = "[^/]+";
private static final String REGEX_ANY_FIELD_NAME = "[^{]+";
private static final String REGEX_ANY_CLASS_NAME = "[^}]+";
private static final String REGEX_ANY_CLASS = "\\{" + REGEX_ANY_CLASS_NAME + "\\}";
private static final String REGEX_ANY_FIELD_NAME = "[^{]*";
private static final String REGEX_ANY_CLASS_NAME = "[^}]*";
private static final String REGEX_ANY_FIELD = "[^{]+";
private static final String REGEX_ANY_CLASS = "\\{[^}]+\\}";
private static final String BRACE_START = "{";
private static final String ESCAPE = "\\";
private static final String BRACE_END = "}";
@ -150,7 +151,7 @@ public class OmniAccessor {
} else if (querySegment.equals(STAR)) {
return REGEX_ANY_NAME;
} else if (querySegment.startsWith(BRACE_START)) {
return REGEX_ANY_FIELD_NAME + querySegment.replace(BRACE_START, ESCAPE + BRACE_START)
return REGEX_ANY_FIELD + querySegment.replace(BRACE_START, ESCAPE + BRACE_START)
.replace(BRACE_END, ESCAPE + BRACE_END)
.replace(BRACKET_START, ESCAPE + BRACKET_START)
.replace(BRACKET_END, ESCAPE + BRACKET_END)

View File

@ -60,12 +60,12 @@ class OmniAccessorTest {
assertEquals(".*/[^{]+\\{Abc\\[\\]\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "{Abc[]}/{Xyz[]}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{Xyz\\[\\]\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc[1]/{Xyz[]}[2]"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{Xyz\\}/demo\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{Xyz}/demo"));
assertEquals(".*/abc\\{[^}]+\\}/de[^{]+\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/de*/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+mo\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/*mo/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/d[^{]+o\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/d*o/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{De[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{De*}/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{[^}]+mo\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{*mo}/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{D[^}]+o\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{D*o}/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/de[^{]*\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/de*/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]*mo\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/*mo/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/d[^{]*o\\{[^}]+\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/d*o/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{De[^}]*\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{De*}/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{[^}]*mo\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{*mo}/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^{]+\\{D[^}]*o\\}/[^{]+\\{Xyz\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/{D*o}/{Xyz}"));
assertEquals(".*/abc\\{[^}]+\\}/[^/]+/[^{]+\\{Xyz\\}/[^/]+/demo\\{[^}]+\\}", PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "toPattern", "abc/*/{Xyz}/*/demo"));
}