1 | package com.github.dakusui.actionunit.actions.cmd; | |
2 | ||
3 | import com.github.dakusui.actionunit.actions.ContextVariable; | |
4 | import com.github.dakusui.actionunit.actions.RetryOption; | |
5 | import com.github.dakusui.actionunit.core.Action; | |
6 | import com.github.dakusui.actionunit.core.Context; | |
7 | import com.github.dakusui.actionunit.core.context.StreamGenerator; | |
8 | import com.github.dakusui.actionunit.exceptions.ActionException; | |
9 | import com.github.dakusui.processstreamer.core.process.ProcessStreamer.Checker; | |
10 | import org.slf4j.Logger; | |
11 | import org.slf4j.LoggerFactory; | |
12 | ||
13 | import java.io.File; | |
14 | import java.util.Collections; | |
15 | import java.util.LinkedHashMap; | |
16 | import java.util.Map; | |
17 | import java.util.Optional; | |
18 | import java.util.function.*; | |
19 | import java.util.stream.Stream; | |
20 | ||
21 | import static com.github.dakusui.actionunit.core.ActionSupport.named; | |
22 | import static java.lang.String.format; | |
23 | import static java.util.Collections.emptyMap; | |
24 | import static java.util.Objects.requireNonNull; | |
25 | ||
26 | /** | |
27 | * A base builder class to construct an action that runs a command line program. | |
28 | * | |
29 | * @param <C> A class refers to itself. | |
30 | * @see com.github.dakusui.actionunit.actions.cmd.unix.Cmd | |
31 | */ | |
32 | public abstract class Commander<C extends Commander<C>> implements Cloneable { | |
33 | private static final Logger LOGGER = LoggerFactory.getLogger(Commander.class); | |
34 | CommandLineComposer.Builder commandLineComposerBuilder; | |
35 | private final Function<ContextVariable[], IntFunction<String>> parameterPlaceHolderFactory; | |
36 | ||
37 | private RetryOption retryOption; | |
38 | private Supplier<Consumer<String>> downstreamConsumerFactory; | |
39 | private Supplier<Checker> checkerFactory; | |
40 | private Stream<String> stdin; | |
41 | ||
42 | private ShellManager shellManager; | |
43 | ||
44 | private File cwd = null; | |
45 | private final Map<String, String> envvars; | |
46 | private String description = null; | |
47 | private String host; | |
48 | ||
49 | ||
50 | protected Commander(CommanderConfig config, String commandName) { | |
51 | this.parameterPlaceHolderFactory = config.variablePlaceHolderFormatter(); | |
52 | this.envvars = new LinkedHashMap<>(); | |
53 | this.stdin(Stream.empty()) | |
54 | .retryOption(config.retryOption()) | |
55 | .shellManager(config.shellManager()) | |
56 | .host("localhost") | |
57 | .checker(config.checker()) | |
58 | .downstreamConsumer(LOGGER::trace); | |
59 | this.commandName(resolveCommandName(config, commandName)); | |
60 | } | |
61 | ||
62 | String resolveCommandName(CommanderConfig config, String commandName) { | |
63 |
1
1. resolveCommandName : replaced return value with "" for com/github/dakusui/actionunit/actions/cmd/Commander::resolveCommandName → KILLED |
return config.programNameResolver().apply(this.host(), commandName); |
64 | } | |
65 | ||
66 | @SuppressWarnings("unchecked") | |
67 | public C describe(String description) { | |
68 | this.description = description; | |
69 |
1
1. describe : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::describe → KILLED |
return (C) this; |
70 | } | |
71 | ||
72 | @SuppressWarnings("unchecked") | |
73 | public C host(String host) { | |
74 | this.host = requireNonNull(host); | |
75 |
1
1. host : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::host → KILLED |
return (C) this; |
76 | } | |
77 | ||
78 | @SuppressWarnings("unchecked") | |
79 | public C clone() { | |
80 | try { | |
81 | C ret = (C) super.clone(); | |
82 |
1
1. clone : negated conditional → KILLED |
if (ret.commandLineComposerBuilder().isPresent()) |
83 | ret.commandLineComposerBuilder = ret.commandLineComposerBuilderIfSet().clone(); | |
84 |
1
1. clone : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::clone → KILLED |
return ret; |
85 | } catch (CloneNotSupportedException e) { | |
86 | throw ActionException.wrap(e); | |
87 | } | |
88 | } | |
89 | ||
90 | @SuppressWarnings("unchecked") | |
91 | public C retryOption(RetryOption retryOption) { | |
92 | this.retryOption = retryOption; | |
93 |
1
1. retryOption : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::retryOption → KILLED |
return (C) this; |
94 | } | |
95 | ||
96 | /** | |
97 | * Sets a down-stream consumer to this builder object. | |
98 | * In case the down-stream consumer is stateful, use {@link Commander#downstreamConsumerFactory(Supplier)} | |
99 | * method instead and give a supplier that returns a new consumer object every time | |
100 | * when its {@code get()} method is called. | |
101 | * | |
102 | * @param downstreamConsumer A down-stream consumer. | |
103 | * @return This object | |
104 | */ | |
105 | public C downstreamConsumer(Consumer<String> downstreamConsumer) { | |
106 | requireNonNull(downstreamConsumer); | |
107 |
2
1. downstreamConsumer : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::downstreamConsumer → KILLED 2. lambda$downstreamConsumer$0 : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::lambda$downstreamConsumer$0 → KILLED |
return this.downstreamConsumerFactory(() -> downstreamConsumer); |
108 | } | |
109 | ||
110 | /** | |
111 | * Sets a downstream consumer's factory to this builder object. | |
112 | * | |
113 | * @param downstreamConsumerFactory A supplier of a down-stream consumer. | |
114 | * @return This object | |
115 | */ | |
116 | @SuppressWarnings("unchecked") | |
117 | public C downstreamConsumerFactory(Supplier<Consumer<String>> downstreamConsumerFactory) { | |
118 | this.downstreamConsumerFactory = requireNonNull(downstreamConsumerFactory); | |
119 |
1
1. downstreamConsumerFactory : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::downstreamConsumerFactory → KILLED |
return (C) this; |
120 | } | |
121 | ||
122 | /** | |
123 | * Sets a checker to this builder object. | |
124 | * In case the checker is stateful, use {@link Commander#checkerFactory(Supplier)} | |
125 | * method instead and give a suuplier that returns a new checker object every | |
126 | * time when its {@code get()} method is called. | |
127 | * | |
128 | * @param checker A checker object | |
129 | * @return This object | |
130 | */ | |
131 | public C checker(Checker checker) { | |
132 | requireNonNull(checker); | |
133 |
2
1. checker : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::checker → KILLED 2. lambda$checker$1 : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::lambda$checker$1 → KILLED |
return this.checkerFactory(() -> checker); |
134 | } | |
135 | ||
136 | @SuppressWarnings("unchecked") | |
137 | public C checkerFactory(Supplier<Checker> checkerFactory) { | |
138 | this.checkerFactory = requireNonNull(checkerFactory); | |
139 |
1
1. checkerFactory : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::checkerFactory → KILLED |
return (C) this; |
140 | } | |
141 | ||
142 | @SuppressWarnings("unchecked") | |
143 | public C stdin(Stream<String> stdin) { | |
144 | this.stdin = requireNonNull(stdin); | |
145 |
1
1. stdin : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::stdin → KILLED |
return (C) this; |
146 | } | |
147 | ||
148 | @SuppressWarnings("unchecked") | |
149 | public C shellManager(ShellManager shellManager) { | |
150 | this.shellManager = requireNonNull(shellManager); | |
151 |
1
1. shellManager : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::shellManager → KILLED |
return (C) this; |
152 | } | |
153 | ||
154 | @SuppressWarnings("unchecked") | |
155 | public C cwd(File cwd) { | |
156 | this.cwd = requireNonNull(cwd); | |
157 |
1
1. cwd : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::cwd → KILLED |
return (C) this; |
158 | } | |
159 | ||
160 | @SuppressWarnings("unchecked") | |
161 | public C setenv(String varname, String varvalue) { | |
162 | this.envvars.put(requireNonNull(varname), requireNonNull(varvalue)); | |
163 |
1
1. setenv : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::setenv → KILLED |
return (C) this; |
164 | } | |
165 | ||
166 | /** | |
167 | * A building method that returns an {@link Action} object. | |
168 | * | |
169 | * @return An action object. | |
170 | */ | |
171 | public Action toAction() { | |
172 | Action action = CommanderUtils.createAction(this); | |
173 |
2
1. toAction : negated conditional → KILLED 2. toAction : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::toAction → KILLED |
return this.description != null ? |
174 | named(this.description, action) : | |
175 | action; | |
176 | } | |
177 | ||
178 | public Action build() { | |
179 |
1
1. build : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::build → KILLED |
return toAction(); |
180 | } | |
181 | ||
182 | public Action $() { | |
183 |
1
1. $ : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::$ → KILLED |
return build(); |
184 | } | |
185 | ||
186 | /** | |
187 | * A building method that returns {@link StreamGenerator} object. | |
188 | * | |
189 | * @return A stream generator object. | |
190 | */ | |
191 | public Function<Context, Stream<String>> toStreamGenerator() { | |
192 |
1
1. toStreamGenerator : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::toStreamGenerator → KILLED |
return CommanderUtils.createStreamGenerator(this); |
193 | } | |
194 | ||
195 | public Consumer<Context> toContextConsumer() { | |
196 |
1
1. toContextConsumer : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::toContextConsumer → KILLED |
return CommanderUtils.createContextConsumer(this); |
197 | } | |
198 | ||
199 | public Predicate<Context> toContextPredicate() { | |
200 |
1
1. toContextPredicate : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::toContextPredicate → KILLED |
return CommanderUtils.createContextPredicate(this); |
201 | } | |
202 | ||
203 | public Function<Context, String> toContextFunction() { | |
204 |
1
1. toContextFunction : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::toContextFunction → KILLED |
return CommanderUtils.createContextFunction(this); |
205 | } | |
206 | ||
207 | /** | |
208 | * A short-hand method to execute a command directly. | |
209 | * | |
210 | * @return data stream from the executed command. | |
211 | */ | |
212 | public Stream<String> run() { | |
213 |
1
1. run : replaced return value with Stream.empty for com/github/dakusui/actionunit/actions/cmd/Commander::run → KILLED |
return run(emptyMap()); |
214 | } | |
215 | ||
216 | /** | |
217 | * A short-hand method to execute a command directly. | |
218 | * | |
219 | * @param variables Variables to be set to the context. | |
220 | * @return data stream from the executed command. | |
221 | */ | |
222 | public Stream<String> run(Map<String, Object> variables) { | |
223 | Context context = Context.create(); | |
224 |
1
1. run : removed call to java/util/Map::forEach → SURVIVED |
requireNonNull(variables).forEach(context::assignTo); |
225 |
1
1. run : replaced return value with Stream.empty for com/github/dakusui/actionunit/actions/cmd/Commander::run → KILLED |
return toStreamGenerator().apply(context); |
226 | } | |
227 | ||
228 | /** | |
229 | * Adds a {@code target} to this object. A target may be a file, directory, or a | |
230 | * message. For instance, for a {@code cat} command, which usually processes | |
231 | * a file or files, this method will be used to add a file to be processed by | |
232 | * the command. | |
233 | * The value of the {@code target} parameter will be quoted. | |
234 | * | |
235 | * @param target A target string | |
236 | * @return This object | |
237 | */ | |
238 | public C add(Function<Context, String> target) { | |
239 |
1
1. add : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::add → KILLED |
return this.append(" ").appendq(requireNonNull(target)); |
240 | } | |
241 | ||
242 | /** | |
243 | * Adds a {@code target} to this object. A target may be a file, directory, or a | |
244 | * message. For instance, for a {@code cat} command, which usually processes | |
245 | * a file or files, this method will be used to add a file to be processed by | |
246 | * the command. | |
247 | * The value of the {@code target} parameter will be quoted. | |
248 | * | |
249 | * @param target A target string | |
250 | * @return This object | |
251 | */ | |
252 | public C add(String target) { | |
253 |
1
1. add : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::add → KILLED |
return this.append(" ").appendq(requireNonNull(target)); |
254 | } | |
255 | ||
256 | public C append(Function<Context, String> func) { | |
257 |
1
1. append : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::append → KILLED |
return append(func, false); |
258 | } | |
259 | ||
260 | public C appendq(Function<Context, String> func) { | |
261 |
1
1. appendq : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::appendq → KILLED |
return append(func, true); |
262 | } | |
263 | ||
264 | @SuppressWarnings("unchecked") | |
265 | public C append(Function<Context, String> func, boolean b) { | |
266 | commandLineComposerBuilderIfSet().append(func, b); | |
267 |
1
1. append : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::append → KILLED |
return (C) this; |
268 | } | |
269 | ||
270 | public C append(String text) { | |
271 |
1
1. append : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::append → KILLED |
return append(text, false); |
272 | } | |
273 | ||
274 | public C appendq(String text) { | |
275 |
1
1. appendq : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::appendq → KILLED |
return append(text, true); |
276 | } | |
277 | ||
278 | @SuppressWarnings("unchecked") | |
279 | public C append(String text, boolean b) { | |
280 | commandLineComposerBuilderIfSet().append(text, b); | |
281 |
1
1. append : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::append → KILLED |
return (C) this; |
282 | } | |
283 | ||
284 | public C addOption(String option) { | |
285 |
1
1. addOption : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::addOption → KILLED |
return this.append(" ").append(option); |
286 | } | |
287 | ||
288 | public C appendVariable(ContextVariable variableName) { | |
289 |
1
1. appendVariable : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::appendVariable → KILLED |
return appendVariable(variableName, false); |
290 | } | |
291 | ||
292 | public C appendQuotedVariable(ContextVariable variableName) { | |
293 |
1
1. appendQuotedVariable : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::appendQuotedVariable → KILLED |
return appendVariable(variableName, true); |
294 | } | |
295 | ||
296 | @SuppressWarnings("unchecked") | |
297 | public C appendVariable(ContextVariable variableName, boolean b) { | |
298 | commandLineComposerBuilderIfSet().appendVariable(variableName, b); | |
299 |
1
1. appendVariable : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::appendVariable → KILLED |
return (C) this; |
300 | } | |
301 | ||
302 | @SuppressWarnings("unchecked") | |
303 | public C declareVariable(ContextVariable variableName) { | |
304 | this.commandLineComposerBuilderIfSet().declareVariable(variableName); | |
305 |
1
1. declareVariable : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::declareVariable → KILLED |
return (C) this; |
306 | } | |
307 | ||
308 | public RetryOption retryOption() { | |
309 |
1
1. retryOption : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::retryOption → KILLED |
return this.retryOption; |
310 | } | |
311 | ||
312 | public Supplier<Checker> checkerFactory() { | |
313 |
1
1. checkerFactory : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::checkerFactory → KILLED |
return this.checkerFactory; |
314 | } | |
315 | ||
316 | public Supplier<Consumer<String>> downstreamConsumerFactory() { | |
317 |
1
1. downstreamConsumerFactory : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::downstreamConsumerFactory → KILLED |
return this.downstreamConsumerFactory; |
318 | } | |
319 | ||
320 | public Stream<String> stdin() { | |
321 |
1
1. stdin : replaced return value with Stream.empty for com/github/dakusui/actionunit/actions/cmd/Commander::stdin → KILLED |
return this.stdin; |
322 | } | |
323 | ||
324 | public ShellManager shellManager() { | |
325 |
1
1. shellManager : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::shellManager → KILLED |
return this.shellManager; |
326 | } | |
327 | ||
328 | public Map<String, String> envvars() { | |
329 |
1
1. envvars : replaced return value with Collections.emptyMap for com/github/dakusui/actionunit/actions/cmd/Commander::envvars → KILLED |
return Collections.unmodifiableMap(this.envvars); |
330 | } | |
331 | ||
332 | public Optional<File> cwd() { | |
333 |
1
1. cwd : replaced return value with Optional.empty for com/github/dakusui/actionunit/actions/cmd/Commander::cwd → SURVIVED |
return Optional.ofNullable(this.cwd); |
334 | } | |
335 | ||
336 | @Override | |
337 | public String toString() { | |
338 |
1
1. toString : replaced return value with "" for com/github/dakusui/actionunit/actions/cmd/Commander::toString → SURVIVED |
return format( |
339 | "%s:Shell:(%s), CommandLine(%s)", | |
340 | this.getClass().getSimpleName(), | |
341 | shellManager(), | |
342 | commandLineComposerBuilder); | |
343 | } | |
344 | ||
345 | @SuppressWarnings("unchecked") | |
346 | public C commandName(String command) { | |
347 | this.commandLineComposerBuilder = new CommandLineComposer.Builder(this.parameterPlaceHolderFactory()) | |
348 | .append(command, false); | |
349 |
1
1. commandName : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::commandName → KILLED |
return (C) this; |
350 | } | |
351 | ||
352 | protected CommandLineComposer.Builder commandLineComposerBuilderIfSet() { | |
353 |
1
1. commandLineComposerBuilderIfSet : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::commandLineComposerBuilderIfSet → KILLED |
return this.commandLineComposerBuilder().orElseThrow(IllegalStateException::new); |
354 | } | |
355 | ||
356 | public CommandLineComposer buildCommandLineComposer() { | |
357 |
1
1. buildCommandLineComposer : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::buildCommandLineComposer → KILLED |
return commandLineComposerBuilderIfSet().clone().build(); |
358 | } | |
359 | ||
360 | Checker checker() { | |
361 |
1
1. checker : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::checker → KILLED |
return this.checkerFactory.get(); |
362 | } | |
363 | ||
364 | Consumer<String> downstreamConsumer() { | |
365 |
1
1. downstreamConsumer : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::downstreamConsumer → KILLED |
return this.downstreamConsumerFactory.get(); |
366 | } | |
367 | ||
368 | ContextVariable[] variables() { | |
369 |
1
1. variables : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::variables → KILLED |
return commandLineComposerBuilderIfSet().knownVariables(); |
370 | } | |
371 | ||
372 | Optional<CommandLineComposer.Builder> commandLineComposerBuilder() { | |
373 |
1
1. commandLineComposerBuilder : replaced return value with Optional.empty for com/github/dakusui/actionunit/actions/cmd/Commander::commandLineComposerBuilder → KILLED |
return Optional.ofNullable(commandLineComposerBuilder); |
374 | } | |
375 | ||
376 | private Function<ContextVariable[], IntFunction<String>> parameterPlaceHolderFactory() { | |
377 |
1
1. parameterPlaceHolderFactory : replaced return value with null for com/github/dakusui/actionunit/actions/cmd/Commander::parameterPlaceHolderFactory → KILLED |
return this.parameterPlaceHolderFactory; |
378 | } | |
379 | ||
380 | public String host() { | |
381 |
1
1. host : replaced return value with "" for com/github/dakusui/actionunit/actions/cmd/Commander::host → KILLED |
return this.host; |
382 | } | |
383 | } | |
Mutations | ||
63 |
1.1 |
|
69 |
1.1 |
|
75 |
1.1 |
|
82 |
1.1 |
|
84 |
1.1 |
|
93 |
1.1 |
|
107 |
1.1 2.2 |
|
119 |
1.1 |
|
133 |
1.1 2.2 |
|
139 |
1.1 |
|
145 |
1.1 |
|
151 |
1.1 |
|
157 |
1.1 |
|
163 |
1.1 |
|
173 |
1.1 2.2 |
|
179 |
1.1 |
|
183 |
1.1 |
|
192 |
1.1 |
|
196 |
1.1 |
|
200 |
1.1 |
|
204 |
1.1 |
|
213 |
1.1 |
|
224 |
1.1 |
|
225 |
1.1 |
|
239 |
1.1 |
|
253 |
1.1 |
|
257 |
1.1 |
|
261 |
1.1 |
|
267 |
1.1 |
|
271 |
1.1 |
|
275 |
1.1 |
|
281 |
1.1 |
|
285 |
1.1 |
|
289 |
1.1 |
|
293 |
1.1 |
|
299 |
1.1 |
|
305 |
1.1 |
|
309 |
1.1 |
|
313 |
1.1 |
|
317 |
1.1 |
|
321 |
1.1 |
|
325 |
1.1 |
|
329 |
1.1 |
|
333 |
1.1 |
|
338 |
1.1 |
|
349 |
1.1 |
|
353 |
1.1 |
|
357 |
1.1 |
|
361 |
1.1 |
|
365 |
1.1 |
|
369 |
1.1 |
|
373 |
1.1 |
|
377 |
1.1 |
|
381 |
1.1 |