diff --git a/bin/deepstate/extract.py b/bin/deepstate/extract.py new file mode 100644 index 00000000..89c72171 --- /dev/null +++ b/bin/deepstate/extract.py @@ -0,0 +1,52 @@ +# +# 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, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function +import argparse + + +def main(): + global candidateRuns, currentTest, s, passStart + + parser = argparse.ArgumentParser(description="Extract standalone test information from a DeepState harness run") + + parser.add_argument( + "run", type=str, help="Path to DeepState run output.") + parser.add_argument( + "template", type=str, help="Path to test template.") + parser.add_argument( + "output_file", type=str, help="Path to output standalone test.") + + args = parser.parse_args() + + run = [] + with open(args.run, 'r') as rfile: + for line in rfile: + run.append(line) + + newSource = [] + with open(args.template, 'r') as tfile: + for line in tfile: + if "<>" not in line: + newSource.append(line) + else: + for line in run: + if "/* START STANDALONE CODE */" in line: + newLine = line.split("/* START STANDALONE CODE */")[1] + newLine = newLine.split("/* END STANDALONE CODE */")[0] + newLine += "\n" + print(newLine[:-1]) + newSource.append(newLine) + + with open(args.output_file, 'w') as ntfile: + for line in newSource: + ntfile.write(line) + +if "__main__" == __name__: + exit(main()) diff --git a/bin/deepstate/standalone.py b/bin/deepstate/standalone.py new file mode 100644 index 00000000..ecc53c2f --- /dev/null +++ b/bin/deepstate/standalone.py @@ -0,0 +1,92 @@ +# +# 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, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import print_function +import argparse + + +def main(): + global candidateRuns, currentTest, s, passStart + + parser = argparse.ArgumentParser(description="Add code to a DeepState harness to dump code for standalone test cases") + + parser.add_argument( + "source", type=str, help="Path to input harness file.") + parser.add_argument( + "output_source", type=str, help="Path to output modified harness file.") + parser.add_argument( + "config", type=str, help="Path for configuration file listing functions to export to standalone.") + + args = parser.parse_args() + + functions = [] + + def annotate(call, f): + annotated = "" + pos = 0 + spaces = "" + for c in call: + if c.isspace(): + spaces += c + pos += 1 + else: + break + arguments = call.split(f + "(")[1] + arguments = arguments.split(")")[0] + theArgs = arguments.split(",") + annotated += "LOG(TRACE) << " + annotated += '"/* START STANDALONE CODE */' + spaces + call[pos:call.find("(") + 1] + '" << ' + if f != "assert": + for arg in theArgs[:-1]: + annotated += ("DeepState_Standalone_Wrap(" + arg + ') << ", " << ') + if len(theArgs) >= 1: + annotated += ("DeepState_Standalone_Wrap(" + theArgs[-1] + ') << ') + else: + for i in range(1, len(call)): + if call[-i] == ")": + endPos = i + break + annotated += '"' + call[call.find("(")+1:-endPos] + '" << ' + annotated += '"); /* END STANDALONE CODE */";\n' + return annotated + + with open(args.config, 'r') as cfile: + for line in cfile: + functions.append(line.split()[0]) + + for f in functions: + print("ADDING STANDALONE TEST GENERATION CODE FOR", f) + + functions.append("assert") + + oldSource = [] + with open(args.source, 'r') as sfile: + for line in sfile: + oldSource.append(line); + + newSource = [] + inTests = False + for line in oldSource: + if inTests: + for f in functions: + if f+"(" in line: + print("ADDING TEST GENERATION CODE FOR:", line[:-1]) + a = annotate(line, f) + print(a) + newSource.append(a) + elif "TEST(" in line: + inTests = True + newSource.append(line) + + with open(args.output_source, 'w') as nsfile: + for line in newSource: + nsfile.write(line) + +if "__main__" == __name__: + exit(main()) diff --git a/bin/setup.py.in b/bin/setup.py.in index 72580464..105d0019 100644 --- a/bin/setup.py.in +++ b/bin/setup.py.in @@ -48,6 +48,9 @@ setuptools.setup( 'deepstate-honggfuzz = deepstate.executors.fuzz.honggfuzz:main', 'deepstate-reduce = deepstate.executors.auxiliary.reducer:main', - 'deepstate-ensembler = deepstate.executors.auxiliary.ensembler:main' + 'deepstate-ensembler = deepstate.executors.auxiliary.ensembler:main', + + 'deepstate-add-standalone = deepstate.standalone:main', + 'deepstate-extract-standalone = deepstate.extract:main', ] }) diff --git a/src/include/deepstate/DeepState.hpp b/src/include/deepstate/DeepState.hpp index 9a31ddb9..e0196111 100644 --- a/src/include/deepstate/DeepState.hpp +++ b/src/include/deepstate/DeepState.hpp @@ -116,6 +116,25 @@ DEEPSTATE_INLINE static bool IsSymbolic(double x) { return DeepState_IsSymbolicDouble(x); } +DEEPSTATE_INLINE static int DeepState_Standalone_Wrap(int x) { + return x; +} + +DEEPSTATE_INLINE static unsigned int DeepState_Standalone_Wrap(unsigned int x) { + return x; +} + +DEEPSTATE_INLINE static std::string DeepState_Standalone_Wrap(char* x) { + if (x == NULL) { + return std::string("NULL"); + } else { + std::string s = "\""; + s += std::string(x); + s += "\""; + return s; + } +} + // A test fixture. class Test { public: