Skip to content

Commit 96a265a

Browse files
authored
Testability aids (#55)
* Uniform logging * Report plugin with all needed (hopefully) data * API to get/set plugin settings
1 parent 8dffe51 commit 96a265a

File tree

61 files changed

+496
-137
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+496
-137
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ java -jar protocol-runner.jar -protocol http -proxy 9999 \
9696
* Plugin-based architecture
9797
* Custom maven repository on [https://maven.kendar.org](https://maven.kendar.org/maven2/releases/org/kendar/protocol/)
9898
* More than 70% Test coverage, more than 550 tests
99+
* Environment-based dynamic settings (see TPM_REPLACE)
99100

100101
The configuration is based on command line parameters or a json properties file
101102
for the usage check [here](docs/properties.md)
@@ -132,6 +133,9 @@ If you want to go on the specific functions by protocol:
132133

133134
```
134135
The Protocol Master
136+
If an environment variable exists TPM_REPLACE=a=b,c=d,e=f
137+
every occurrence of %a% in config file is replaced with
138+
b value and so on
135139
136140
un unattended Unattended run (default false)
137141
cfg config Load config file

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
</modules>
2525

2626
<properties>
27-
<revision>2.3.3</revision>
27+
<revision>2.3.4</revision>
2828
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2929
<maven.compiler.target>17</maven.compiler.target>
3030
<maven.compiler.source>17</maven.compiler.source>

protocol-amqp-091/src/main/java/org/kendar/amqp/v09/apis/AmqpPublishPluginApis.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public AmqpPublishPluginApis(AmqpPublishPlugin descriptor, String id, String ins
4848
body = Ko.class,
4949
description = "In case of errors"
5050
)},
51-
tags = {"plugins/{#protocol}/{#protocolInstanceId}"})
51+
tags = {"plugins/{#protocol}/{#protocolInstanceId}/publish-plugin"})
5252
public void getConnections(Request request, Response response) {
5353
var pInstance = getDescriptor().getProtocolInstance();
5454
var result = new ArrayList<AmqpConnection>();

protocol-amqp-091/src/main/java/org/kendar/amqp/v09/plugins/AmqpReplayPlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ protected void sendBackResponses(ProtoContext context, List<StorageItem> storage
9696
var bd = mapper.deserialize(out, BasicDeliver.class);
9797
var tag = (String) ctx.getValue("BASIC_CONSUME_CT_" + bd.getConsumeOrigin());
9898

99-
log.debug("Delivering " + "BASIC_CONSUME_CT_" + bd.getConsumeOrigin() + " " + tag);
99+
log.trace("BasicDeliver tag{}", tag);
100100
if (tag != null && !tag.isEmpty()) {
101101
bd.setConsumerTag(tag);
102102
}

protocol-amqp-091/src/main/java/org/kendar/amqp/v09/plugins/AmqpReportPlugin.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,27 @@ public boolean handle(PluginContext pluginContext, ProtocolPhase phase, BodyFram
6464
));
6565
return false;
6666
}
67+
68+
public boolean handle(PluginContext pluginContext, ProtocolPhase phase, Object in, BodyFrame out) {
69+
if (!isActive() && phase!=ProtocolPhase.ASYNC_RESPONSE) return false;
70+
71+
var context = pluginContext.getContext();
72+
var connectionId = context.getContextId();
73+
var channel = out.getChannel();
74+
var routingKey = context.getValue("BASIC_PUBLISH_RK_" + out.getChannel());
75+
var exchange = context.getValue("BASIC_PUBLISH_XC_" + out.getChannel());
76+
var payload = mapper.toHumanReadable(out.getContent());
77+
78+
var duration = System.currentTimeMillis() - pluginContext.getStart();
79+
EventsQueue.send(new ReportDataEvent(
80+
getInstanceId(),
81+
getProtocol(),
82+
String.format("RECEIVE:%s:%s", exchange, routingKey),
83+
connectionId,
84+
pluginContext.getStart(),
85+
duration,
86+
Map.of("body", payload, "channel", channel + "")
87+
));
88+
return false;
89+
}
6790
}

protocol-amqp-091/src/test/java/org/kendar/amqp/v09/ExchangeTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void testExchange() throws URISyntaxException, NoSuchAlgorithmException, KeyMana
8181
assertTrue(Square.results.containsKey("Square of 4 is: 16"));
8282
assertTrue(Square.results.containsKey("Square of 5 is: 25"));
8383
var events = getEvents().stream().collect(Collectors.toList());
84-
assertEquals(7, events.size());
84+
assertEquals(12, events.size());
8585
assertEquals(2, events.stream().filter(e -> e.getQuery().equalsIgnoreCase("CONNECT")).count());
8686
}
8787
}

protocol-common-jdbc/src/main/java/org/kendar/sql/jdbc/JdbcProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ public ProxyConnection connect(NetworkProtoContext context) {
378378
}
379379
return new ProxyConnection(connection);
380380
} catch (SQLException e) {
381-
log.warn("Error connection {}", getConnectionString(), e);
381+
log.warn("Error connection `{}`", getConnectionString());
382382
return new ProxyConnection(null);
383383
}
384384
}

protocol-common/src/main/java/org/kendar/annotations/multi/TpmRequest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@
3232
*/
3333
Class<?> body() default Object.class;
3434

35+
/**
36+
* Function to call for body type
37+
*
38+
* @return
39+
*/
40+
String bodyMethod() default "";
41+
3542
/**
3643
* If optional
3744
*

protocol-common/src/main/java/org/kendar/annotations/multi/TpmResponse.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939
*/
4040
Class<?> body() default Object.class;
4141

42+
/**
43+
* Function to call for body type
44+
*
45+
* @return
46+
*/
47+
String bodyMethod() default "";
48+
4249
/**
4350
* Returned headers
4451
*

protocol-common/src/main/java/org/kendar/apis/FilterDescriptor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import org.kendar.apis.utils.GenericFilterExecutor;
1818
import org.kendar.apis.utils.IdBuilder;
1919
import org.kendar.plugins.base.ProtocolPluginApiHandler;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
2022

2123
import java.lang.annotation.IncompleteAnnotationException;
2224
import java.lang.reflect.InvocationTargetException;
@@ -204,6 +206,19 @@ public boolean matches(Request req) {
204206
}
205207
return true;
206208
}
209+
private static final Logger log = LoggerFactory.getLogger(FilterDescriptor.class);
210+
211+
public Object invokeOnFilterClass(String name,Object...args){
212+
if(name==null || name.isEmpty()) return null;
213+
try {
214+
var method = filterClass.getClass().getMethod(name);
215+
method.setAccessible(true);
216+
return method.invoke(filterClass, args);
217+
}catch (Exception e) {
218+
log.error("Error retrieving data from {}",filterClass.getClass().getName(),e);
219+
return null;
220+
}
221+
}
207222

208223
/**
209224
* Run the callback associate with the address

protocol-common/src/main/java/org/kendar/cli/CommandOption.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ public class CommandOption implements CommandItem {
2424
private boolean present;
2525
private String subChoicesDescription;
2626
private CommandItem parent;
27+
private boolean multiple;
28+
private Consumer<List<String>> multiCallback;
29+
30+
public CommandOption asMultiple() {
31+
this.multiple = true;
32+
return this;
33+
}
2734

2835
private CommandOption(String shortCommand, String description) {
2936

@@ -144,8 +151,15 @@ public List<String> getValues() {
144151
}
145152

146153
public void setValues(List<String> values) {
147-
this.values = values;
148-
if (callback != null) {
154+
if(this.values == null){
155+
this.values = values;
156+
}else{
157+
this.values.addAll(values);
158+
}
159+
160+
if (multiCallback != null) {
161+
multiCallback.accept(this.values);
162+
}else if (callback != null) {
149163
if (!this.isHasParameter()) {
150164
callback.accept(null);
151165
} else {
@@ -209,6 +223,11 @@ public CommandOption withCallback(Consumer<String> callback) {
209223
return this;
210224
}
211225

226+
public CommandOption withMultiCallback(Consumer<List<String>> callback) {
227+
this.multiCallback = callback;
228+
return this;
229+
}
230+
212231
public String getSubChoicesDescription() {
213232
return subChoicesDescription;
214233
}
@@ -264,7 +283,7 @@ public boolean hasSubOptions() {
264283
}
265284

266285
public void parseInternal(List<MainArg> mainArgs) {
267-
parseListOfCommands(mainArgs, subOptions, this);
286+
parseListOfCommands(mainArgs, subOptions, this,false);
268287
}
269288

270289
public List<CommandOption> getCommandOptions() {
@@ -282,4 +301,8 @@ public CommandItem getParent() {
282301
public void setParent(CommandItem parent) {
283302
this.parent = parent;
284303
}
304+
305+
public boolean isMultiple() {
306+
return multiple;
307+
}
285308
}

protocol-common/src/main/java/org/kendar/cli/CommandOptions.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static CommandOptions of(String id, String description) {
2929
return new CommandOptions(id, description);
3030
}
3131

32-
protected static void parseListOfCommands(List<MainArg> mainArgs, List<CommandOption> co, CommandItem caller) {
32+
protected static void parseListOfCommands(List<MainArg> mainArgs, List<CommandOption> co, CommandItem caller,boolean multiple) {
3333
for (CommandOption item : co) {
3434
var matchingArgIndex = 0;
3535
var foundedMatchingArg = false;
@@ -74,6 +74,12 @@ protected static void parseListOfCommands(List<MainArg> mainArgs, List<CommandOp
7474
}
7575
item.setValues(arg.get().getValues());
7676
item.setPresent();
77+
if(item.isMultiple()){
78+
parseListOfCommands(mainArgs,co,caller,true);
79+
}
80+
if(multiple){
81+
break;
82+
}
7783
if (item.hasSubOptions()) {
7884
item.parseInternal(mainArgs);
7985
}
@@ -119,7 +125,7 @@ protected static void parseListOfCommands(List<MainArg> mainArgs, List<CommandOp
119125
protected static void printHelpListOfCommands(ArrayList<HelpLine> result, List<CommandOption> co) {
120126
for (var item : co) {
121127
if (item.hasSubChoices()) continue;
122-
result.add(new HelpLine(item.getShortCommand(), item.getLongCommand(), item.getDescription(), null));
128+
result.add(new HelpLine(item.getShortCommand(), item.getLongCommand(), item.getDescription(), null, item.isMultiple()));
123129
if (item.hasSubOptions()) {
124130
for (var choice : item.getCommandOptions()) {
125131
if (choice.getDescription() != null) {
@@ -132,7 +138,7 @@ protected static void printHelpListOfCommands(ArrayList<HelpLine> result, List<C
132138
if (!item.hasSubChoices()) continue;
133139
var choices = item.getSubChoices().stream().map(CommandOptions::getId).collect(Collectors.toCollection(HashSet::new));
134140
var availableChoices = String.join("|", choices);
135-
result.add(new HelpLine(item.getShortCommand(), item.getLongCommand(), item.getDescription(), availableChoices));
141+
result.add(new HelpLine(item.getShortCommand(), item.getLongCommand(), item.getDescription(), availableChoices,item.isMultiple()));
136142
if (item.getSubChoicesDescription() != null) {
137143
result.add(new HelpLine(item.getSubChoicesDescription()));
138144
}
@@ -217,7 +223,7 @@ public void parse(List<MainArg> mainArgs, boolean ignoreMissing) {
217223
}
218224

219225
public void parseInternal(List<MainArg> mainArgs) {
220-
parseListOfCommands(mainArgs, commandOptions, this);
226+
parseListOfCommands(mainArgs, commandOptions, this,false);
221227
}
222228

223229
public boolean hasOption(String id) {

protocol-common/src/main/java/org/kendar/cli/CommandParser.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ public String buildHelp() {
133133
if (item.getAvailableOptions() != null) {
134134
description += "\nOptions: " + item.getAvailableOptions();
135135
}
136+
if (item.isMultiple()) {
137+
description += "\nRepeatable";
138+
}
136139
String[] split = description.split("[\r\n\f]+");
137140
for (int i = 0; i < split.length; i++) {
138141
var descline = split[i];

protocol-common/src/main/java/org/kendar/cli/HelpLine.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ public class HelpLine {
66
private String longCommand;
77
private String description;
88
private String availableOptions;
9+
private boolean multiple;
910

10-
public HelpLine(String shortCommand, String longCommand, String description, String availableOptions) {
11+
public HelpLine(String shortCommand, String longCommand, String description, String availableOptions,boolean multiple) {
1112
this.shortCommand = shortCommand;
1213
this.longCommand = longCommand;
1314
this.description = description;
1415
this.availableOptions = availableOptions;
1516
this.block = false;
17+
this.multiple = multiple;
1618
}
1719

1820
public HelpLine(String description) {
@@ -64,4 +66,12 @@ public String getAvailableOptions() {
6466
public void setAvailableOptions(String availableOptions) {
6567
this.availableOptions = availableOptions;
6668
}
69+
70+
public boolean isMultiple() {
71+
return multiple;
72+
}
73+
74+
public void setMultiple(boolean multiple) {
75+
this.multiple = multiple;
76+
}
6777
}

protocol-common/src/main/java/org/kendar/di/annotations/TpmNamed.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
import java.lang.annotation.RetentionPolicy;
66
import java.lang.annotation.Target;
77

8-
/**
9-
* Assign a base DNS/address to respond to
10-
* Mandatory for @FilterClass
11-
*/
128
@Retention(RetentionPolicy.RUNTIME)
139
@Target({ElementType.TYPE, ElementType.PARAMETER})
1410
public @interface TpmNamed {

protocol-common/src/main/java/org/kendar/events/ReportDataEvent.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,13 @@ public ReportDataEvent(String instanceId,
3434
@Override
3535
public String toString() {
3636
return "ReportDataEvent{" +
37-
"protocol='" + protocol + '\'' +
38-
", instanceId='" + instanceId + '\'' +
37+
"instanceId='" + instanceId + '\'' +
38+
", protocol='" + protocol + '\'' +
3939
", query='" + query + '\'' +
40+
", connectionId=" + connectionId +
41+
", timestamp=" + timestamp +
42+
", duration=" + duration +
43+
", tags=" + tags +
4044
'}';
4145
}
4246

protocol-common/src/main/java/org/kendar/plugins/MockPlugin.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,9 @@ protected abstract void writeOutput(T request, K response,
9494
protected abstract List<MockStorage> firstCheckOnMainPart(T request);
9595

9696
@Override
97-
public ProtocolPluginDescriptor initialize(GlobalSettings global, ProtocolSettings protocol, PluginSettings pluginSetting) {
98-
99-
super.initialize(global, protocol, pluginSetting);
97+
protected boolean handleSettingsChanged(){
10098
if (getSettings().getDataDir() == null) {
101-
return null;
99+
return false;
102100
}
103101
mocksDir = getSettings().getDataDir();
104102
if (!Files.exists(Path.of(mocksDir).toAbsolutePath())) {
@@ -109,6 +107,14 @@ public ProtocolPluginDescriptor initialize(GlobalSettings global, ProtocolSettin
109107
}
110108
}
111109
loadMocks();
110+
return true;
111+
}
112+
@Override
113+
public ProtocolPluginDescriptor initialize(GlobalSettings global, ProtocolSettings protocol, PluginSettings pluginSetting) {
114+
115+
super.initialize(global, protocol, pluginSetting);
116+
if(!handleSettingsChanged())return null;
117+
112118
return this;
113119

114120
}

protocol-common/src/main/java/org/kendar/plugins/RecordPlugin.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,16 @@ public List<ProtocolPhase> getPhases() {
126126
return List.of(ProtocolPhase.PRE_CALL, ProtocolPhase.POST_CALL, ProtocolPhase.ASYNC_RESPONSE);
127127
}
128128

129+
@Override
130+
protected boolean handleSettingsChanged(){
131+
ignoreTrivialCalls = ((BasicRecordPluginSettings) getSettings()).isIgnoreTrivialCalls();
132+
return true;
133+
}
134+
129135
@Override
130136
public ProtocolPluginDescriptor initialize(GlobalSettings global, ProtocolSettings protocol, PluginSettings pluginSetting) {
131-
ignoreTrivialCalls = ((BasicRecordPluginSettings) pluginSetting).isIgnoreTrivialCalls();
132137
super.initialize(global, protocol, pluginSetting);
138+
handleSettingsChanged();
133139
return this;
134140
}
135141

@@ -168,7 +174,7 @@ private void disconnectAll() {
168174
context.disconnect(((ProxyConnection) contextConnection).getConnection());
169175
context.setValue("CONNECTION", null);
170176
} catch (Exception e) {
171-
log.debug("Error disconnecting connection {}", contextKvp.getKey(), e);
177+
log.debug("Error disconnecting {}", contextKvp.getKey(), e);
172178
}
173179
pi.getContextsCache().remove(contextKvp.getKey());
174180
}

0 commit comments

Comments
 (0)