import WebIDL

def WebIDLTest(parser, harness):
    parser.parse("""
        typedef float myFloat;
        typedef unrestricted float myUnrestrictedFloat;
        interface FloatTypes {
          attribute float f;
          attribute unrestricted float uf;
          attribute double d;
          attribute unrestricted double ud;
          [LenientFloat]
          attribute float lf;
          [LenientFloat]
          attribute double ld;

          void m1(float arg1, double arg2, float? arg3, double? arg4,
                  myFloat arg5, unrestricted float arg6,
                  unrestricted double arg7, unrestricted float? arg8,
                  unrestricted double? arg9, myUnrestrictedFloat arg10);
          [LenientFloat]
          void m2(float arg1, double arg2, float? arg3, double? arg4,
                  myFloat arg5, unrestricted float arg6,
                  unrestricted double arg7, unrestricted float? arg8,
                  unrestricted double? arg9, myUnrestrictedFloat arg10);
          [LenientFloat]
          void m3(float arg);
          [LenientFloat]
          void m4(double arg);
          [LenientFloat]
          void m5((float or FloatTypes) arg);
          [LenientFloat]
          void m6(sequence<float> arg);
        };
    """)

    results = parser.finish()

    harness.check(len(results), 3, "Should be two typedefs and one interface.")
    iface = results[2]
    harness.ok(isinstance(iface, WebIDL.IDLInterface),
               "Should be an IDLInterface")
    types = [a.type for a in iface.members if a.isAttr()]
    harness.ok(types[0].isFloat(), "'float' is a float")
    harness.ok(not types[0].isUnrestricted(), "'float' is not unrestricted")
    harness.ok(types[1].isFloat(), "'unrestricted float' is a float")
    harness.ok(types[1].isUnrestricted(), "'unrestricted float' is unrestricted")
    harness.ok(types[2].isFloat(), "'double' is a float")
    harness.ok(not types[2].isUnrestricted(), "'double' is not unrestricted")
    harness.ok(types[3].isFloat(), "'unrestricted double' is a float")
    harness.ok(types[3].isUnrestricted(), "'unrestricted double' is unrestricted")

    method = iface.members[6]
    harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
    argtypes = [a.type for a in method.signatures()[0][1]]
    for (idx, type) in enumerate(argtypes):
        harness.ok(type.isFloat(), "Type %d should be float" % idx)
        harness.check(type.isUnrestricted(), idx >= 5,
                      "Type %d should %sbe unrestricted" % (
                idx, "" if idx >= 4 else "not "))

    parser = parser.reset()
    threw = False
    try:
        parser.parse("""
            interface FloatTypes {
              [LenientFloat]
              long m(float arg);
            };
        """)
    except Exception, x:
        threw = True
    harness.ok(threw, "[LenientFloat] only allowed on void methods")

    parser = parser.reset()
    threw = False
    try:
        parser.parse("""
            interface FloatTypes {
              [LenientFloat]
              void m(unrestricted float arg);
            };
        """)
    except Exception, x:
        threw = True
    harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args")

    parser = parser.reset()
    threw = False
    try:
        parser.parse("""
            interface FloatTypes {
              [LenientFloat]
              void m(sequence<unrestricted float> arg);
            };
        """)
    except Exception, x:
        threw = True
    harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)")

    parser = parser.reset()
    threw = False
    try:
        parser.parse("""
            interface FloatTypes {
              [LenientFloat]
              void m((unrestricted float or FloatTypes) arg);
            };
        """)
    except Exception, x:
        threw = True
    harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)")

    parser = parser.reset()
    threw = False
    try:
        parser.parse("""
            interface FloatTypes {
              [LenientFloat]
              readonly attribute float foo;
            };
        """)
    except Exception, x:
        threw = True
    harness.ok(threw, "[LenientFloat] only allowed on writable attributes")
