• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / learnlib / 16696694729

02 Aug 2025 06:52PM UTC coverage: 94.289% (-0.09%) from 94.383%
16696694729

push

github

mtf90
add CLI membership oracles

closes #149

111 of 131 new or added lines in 4 files covered. (84.73%)

12630 of 13395 relevant lines covered (94.29%)

1.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.82
/oracles/membership-oracles/src/main/java/de/learnlib/oracle/membership/StdInOracle.java
1
/* Copyright (C) 2013-2025 TU Dortmund University
2
 * This file is part of LearnLib <https://learnlib.de>.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package de.learnlib.oracle.membership;
17

18
import java.io.IOException;
19
import java.io.StringReader;
20
import java.util.List;
21
import java.util.Objects;
22

23
import de.learnlib.oracle.SingleQueryOracle;
24
import net.automatalib.common.util.process.ProcessUtil;
25
import net.automatalib.word.Word;
26
import org.checkerframework.checker.nullness.qual.Nullable;
27
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
28
import org.slf4j.Logger;
29
import org.slf4j.LoggerFactory;
30

31
/**
32
 * An oracle that delegates its queries to an external program via the command-line interface. Acceptance of the queries
33
 * is determined based on the program's return code where {@code 0} indicates success and any other value indicates
34
 * failure.
35
 * <p>
36
 * Queries are passed to the program's stdin stream (via the queries' {@link Word#toString()} method. You may adjust
37
 * formatting via the available properties in AutomataLib's settings). Depending on whether a {@code reset} symbol has
38
 * been specified, this oracle assumes either a stateless ({@code reset == null}) or stateful ({@code reset != null})
39
 * communication.
40
 * <p>
41
 * In a stateless communication, all symbols of a query are passed to the program at once and invocations should be
42
 * treated independently from each other. In a stateful communication, the program is executed multiple times with a
43
 * single query symbol each, preceded by a single invocation with only the {@code reset} symbol. The exit code of the
44
 * last invocation determines the query response.
45
 *
46
 * @param <I>
47
 *         input symbol type
48
 */
49
public class StdInOracle<I> implements SingleQueryOracle<I, Boolean> {
50

51
    private static final Logger LOGGER = LoggerFactory.getLogger(StdInOracle.class);
2✔
52

53
    private final List<String> commandLine;
54
    private final @Nullable String reset;
55

56
    /**
57
     * Constructor. Does not set a {@code reset} symbol.
58
     *
59
     * @param commandLine
60
     *         the command line, containing the main binary and potential additional arguments
61
     *
62
     * @see #StdInOracle(List, String)
63
     */
64
    public StdInOracle(List<String> commandLine) {
65
        this(commandLine, null);
2✔
66
    }
2✔
67

68
    /**
69
     * Constructor.
70
     *
71
     * @param commandLine
72
     *         the command line, containing the main binary and potential additional arguments
73
     * @param reset
74
     *         the symbol passed to the program to indicate a reset
75
     */
76
    public StdInOracle(List<String> commandLine, @Nullable String reset) {
2✔
77
        this.commandLine = commandLine;
2✔
78
        this.reset = reset;
2✔
79
    }
2✔
80

81
    @Override
82
    public Boolean answerQuery(Word<I> prefix, Word<I> suffix) {
83
        return reset == null ? answerStatelessQuery(prefix, suffix) : answerStatefulQuery(prefix, suffix);
2✔
84
    }
85

86
    private boolean answerStatelessQuery(Word<I> prefix, Word<I> suffix) {
87
        try {
88
            return ProcessUtil.invokeProcess(commandLine,
2✔
89
                                             new StringReader(prefix.concat(suffix).toString()),
2✔
90
                                             LOGGER::debug,
2✔
91
                                             LOGGER::warn) == 0;
2✔
NEW
92
        } catch (IOException | InterruptedException e) {
×
NEW
93
            LOGGER.warn("Error while invoking process", e);
×
NEW
94
            return false;
×
95
        }
96
    }
97

98
    @RequiresNonNull("this.reset")
99
    private boolean answerStatefulQuery(Word<I> prefix, Word<I> suffix) {
100
        try {
101
            int returnCode =
2✔
102
                    ProcessUtil.invokeProcess(commandLine, new StringReader(reset), LOGGER::debug, LOGGER::warn);
2✔
103

104
            for (I p : prefix) {
2✔
105
                returnCode = ProcessUtil.invokeProcess(commandLine,
2✔
106
                                                       new StringReader(Objects.toString(p)),
2✔
107
                                                       LOGGER::debug,
2✔
108
                                                       LOGGER::warn);
2✔
109
            }
2✔
110

111
            for (I s : suffix) {
2✔
112
                returnCode = ProcessUtil.invokeProcess(commandLine,
2✔
113
                                                       new StringReader(Objects.toString(s)),
2✔
114
                                                       LOGGER::debug,
2✔
115
                                                       LOGGER::warn);
2✔
116
            }
2✔
117

118
            return returnCode == 0;
2✔
NEW
119
        } catch (IOException | InterruptedException e) {
×
NEW
120
            LOGGER.warn("Error while invoking process", e);
×
NEW
121
            return false;
×
122
        }
123
    }
124
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc