aboutsummaryrefslogtreecommitdiff
path: root/build2/test/script/script
blob: b6a0f2176052e39429340b2eba0fdc885645f9da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// file      : build2/test/script/script -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD2_TEST_SCRIPT_SCRIPT
#define BUILD2_TEST_SCRIPT_SCRIPT

#include <build2/types>
#include <build2/utility>

#include <build2/variable>

#include <build2/test/target>

namespace build2
{
  class target;

  namespace test
  {
    namespace script
    {
      enum class redirect_type
      {
        none,
        null,
        here_string,  // Value is the string.
        here_document // Value is the document.
      };

      struct redirect
      {
        redirect_type type = redirect_type::none;
        string value;
      };

      struct command
      {
        path program;
        strings arguments;

        redirect in;
        redirect out;
        redirect err;
      };

      enum class exit_comparison {eq, ne};

      struct command_exit
      {
        // @@ Need to understand what type we should use for status.

        exit_comparison comparison = exit_comparison::eq;
        uint16_t status = 0;
      };

      struct test: command
      {
        command_exit exit;
      };

      class scope
      {
      public:
        scope* parent; // NULL for the root (script) scope.

        scope (scope& p): parent (&p) {}

      protected:
        scope (): parent (nullptr) {} // For the root (script) scope.

        // Variables.
        //
      public:
        // Note that if we pass the variable name as a string, then it will
        // be looked up in the wrong pool.
        //
        variable_map vars;

        // Lookup the variable starting from this scope, continuing with outer
        // scopes, then the target being tested, then the testscript target,
        // and then outer buildfile scopes (including testscript-type/pattern
        // specific).
        //
        lookup
        find (const variable&) const;

        // Return a value suitable for assignment. If the variable does not
        // exist in this scope's map, then a new one with the NULL value is
        // added and returned. Otherwise the existing value is returned.
        //
        value&
        assign (const variable& var) {return vars.assign (var);}

        // Return a value suitable for append/prepend. If the variable does
        // not exist in this scope's map, then outer scopes are searched for
        // the same variable. If found then a new variable with the found
        // value is added to this scope and returned. Otherwise this function
        // proceeds as assign() above.
        //
        value&
        append (const variable&);
      };

      class script: public scope
      {
      public:
        script (target& test_target, testscript& script_target);

      public:
        target& test_target;       // Target we are testing.
        testscript& script_target; // Target of the testscript file.

      public:
        variable_pool var_pool;

        const variable& test_var; // test
        const variable& opts_var; // test.options
        const variable& args_var; // test.arguments

        const variable& cmd_var; // $*
        const variable& cwd_var; // $~
      };
    }
  }
}

#endif // BUILD2_TEST_SCRIPT_SCRIPT