Repository: nginxinc/crossplane

Issue:
NGINX_CONF_FLAG directives should support uppercase ON or OFF as args
`crossplane parse` throws an error for this config but `nginx` does not:
```nginx
events {
    accept_mutex OFF;
}
```

Discussion:

Patch:
diff --git a/crossplane/analyzer.py b/crossplane/analyzer.py
index f5a5ffb..ec89dab 100644
--- a/crossplane/analyzer.py
+++ b/crossplane/analyzer.py
@@ -1920,7 +1920,7 @@ def analyze(fname, stmt, term, ctx=()):
         reason = '"%s" directive is not allowed here' % directive
         raise NgxParserDirectiveContextError(reason, fname, line)
 
-    valid_flag = lambda x: x in ('on', 'off')
+    valid_flag = lambda x: x.lower() in ('on', 'off')
 
     # do this in reverse because we only throw errors at the end if no masks
     # are valid, and typically the first bit mask is what the parser expects
@@ -1942,6 +1942,8 @@ def analyze(fname, stmt, term, ctx=()):
             (mask & NGX_CONF_1MORE and n_args >= 1) or
             (mask & NGX_CONF_2MORE and n_args >= 2)):
             return
+        elif mask & NGX_CONF_FLAG and n_args == 1 and not valid_flag(args[0]):
+            reason = 'invalid value "%s" in "%%s" directive, it must be "on" or "off"' % args[0]
         else:
             reason = 'invalid number of arguments in "%s" directive'
 


Test patch:
diff --git a/tests/test_analyze.py b/tests/test_analyze.py
index ccb4091..8c36815 100644
--- a/tests/test_analyze.py
+++ b/tests/test_analyze.py
@@ -31,3 +31,30 @@ def test_state_directive():
             raise Exception("bad context for 'state' passed: " + repr(ctx))
         except crossplane.errors.NgxParserDirectiveContextError:
             continue
+
+
+def test_flag_directive_args():
+    fname = '/path/to/nginx.conf'
+    ctx = ('events',)
+
+    # an NGINX_CONF_FLAG directive
+    stmt = {
+        'directive': 'accept_mutex',
+        'line': 2  # this is arbitrary
+    }
+
+    good_args = [['on'], ['off'], ['On'], ['Off'], ['ON'], ['OFF']]
+
+    for args in good_args:
+        stmt['args'] = args
+        crossplane.analyzer.analyze(fname, stmt, term=';', ctx=ctx)
+
+    bad_args = [['1'], ['0'], ['true'], ['okay'], ['']]
+
+    for args in bad_args:
+        stmt['args'] = args
+        try:
+            crossplane.analyzer.analyze(fname, stmt, term=';', ctx=ctx)
+            raise Exception('bad args for flag directive: ' + repr(args))
+        except crossplane.errors.NgxParserDirectiveArgumentsError as e:
+            assert e.strerror.endswith('it must be "on" or "off"')