Beispiel #1
0
def test_script_invalid_content_runtime():
    # pylint: disable=invalid-name
    ''' checks that generator.py raises an appropriate error when a
        script file contains valid python syntactically but produces a
        runtime exception. '''
    with pytest.raises(GenerationError):
        _, _ = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                     "1_single_invoke.f90"),
                        api="dynamo0.3",
                        script_name=os.path.join(BASE_PATH, "dynamo0p3",
                                                 "runtime_error.py"))
Beispiel #2
0
def test_multi_kernel_named_invoke():
    ''' Test that we correctly handle a named invoke call that contains
    more than one kernel '''
    alg, _ = generate(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   "test_files", "dynamo0p3",
                                   "4.9_named_multikernel_invokes.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    assert "USE multikernel_invokes_7_psy, ONLY: invoke_some_name" in gen
    assert ("CALL invoke_some_name(a, b, c, istp, rdt, d, ascalar, f, g, e)"
            in gen)
Beispiel #3
0
def test_script_file_not_found_relative():
    # pylint: disable=invalid-name
    ''' checks that generator.py raises an appropriate error when a script
        file is supplied that can't be found in the Python path. In
        this case the script path is not supplied so must be found via the
        PYTHONPATH variable'''
    with pytest.raises(GenerationError):
        _, _ = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                     "1_single_invoke.f90"),
                        api="dynamo0.3",
                        script_name="non_existant.py")
Beispiel #4
0
def test_multi_deref_derived_type_args():
    ''' Test the case where a given kernel argument is specified using
    different derived types in the same invoke. '''
    alg, _ = generate(os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "test_files", "dynamo0p3",
        "1.6.3_single_invoke_multiple_derived_types.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    print(gen)
    assert ("CALL invoke_0(f1, obj_a % iflag, f2, m1, m2, obj_b % iflag, "
            "obj_a % obj_b, obj_b % obj_a)" in gen)
Beispiel #5
0
def test_vector_field_arg_deref():
    ''' Test that we generate a correct invoke call when a kernel
    argument representing a field vector is obtained by de-referencing a
    derived type '''
    alg, _ = generate(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   "test_files", "dynamo0p3",
                                   "8.1_vector_field_deref.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    print(gen)
    assert "CALL invoke_0_testkern_chi_type(f1, box % chi, f2)" in gen
Beispiel #6
0
 def test_single_function_named_invoke(self):
     ''' Test that we correctly handle a named invoke call '''
     alg, _ = generate(
         os.path.join(os.path.dirname(os.path.abspath(__file__)),
                      "test_files", "dynamo0p3",
                      "1.0.1_single_named_invoke.f90"),
         api="dynamo0.3")
     gen = str(alg)
     print gen
     assert "USE single_invoke_psy, ONLY: invoke_important_invoke" in gen
     assert "CALL invoke_important_invoke(a, f1, f2, m1, m2)" in gen
Beispiel #7
0
def test_multi_function_multi_invokes():
    ''' two invokes, each containing multiple functions '''
    alg, _ = generate(os.path.join(BASE_PATH,
                                   "3.1_multi_functions_multi_invokes.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    print(gen)
    assert "USE multi_functions_multi_invokes_psy, ONLY: invoke_1" in gen
    assert "USE multi_functions_multi_invokes_psy, ONLY: invoke_0" in gen
    assert "CALL invoke_0(a, f1, f2, m1, m2, istp, qr)" in gen
    assert "CALL invoke_1(f1, f2, m1, a, m2, istp, qr)" in gen
Beispiel #8
0
def test_op_and_scalar_and_qr_derived_type_args():
    ''' Test the case where the operator, scalar and qr arguments to a
    kernel are all supplied by de-referencing derived types '''
    alg, _ = generate(os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "test_files", "dynamo0p3",
        "10.6.1_operator_no_field_scalar_deref.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    print gen
    assert ("CALL invoke_0_testkern_operator_nofield_scalar_type("
            "opbox%my_mapping, box%b(1), qr%get_instance(qr3, 9, 3))" in gen)
Beispiel #9
0
def test_single_function_multi_invokes():
    ''' three invokes, each containing a single function '''
    alg, _ = generate(os.path.join(BASE_PATH, "3_multi_invokes.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    assert "USE testkern, ONLY: testkern_type" in gen
    assert "USE testkern_qr, ONLY: testkern_qr_type" in gen
    assert "CALL invoke_0_testkern_type(a, f1, f2, m1, m2)" in gen
    assert "CALL invoke_2_testkern_type(a, f1, f2, m1, m2)" in gen
    assert ("CALL invoke_1_testkern_qr_type(f1, f2, m1, a, m2, istp, qr)"
            in gen)
Beispiel #10
0
def test_single_invoke_dynamo0p1():
    ''' Test for correct code transformation for a single function
        specified in an invoke call for the dynamo0.1 API. We use the
        generate function as parse and PSyFactory need to be called before
        AlgGen so it is simpler to use this. '''
    alg, _ = generate(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   "test_files", "dynamo0p1", "algorithm",
                                   "1_single_function.f90"),
                      api="dynamo0.1")
    gen = str(alg)
    assert "USE psy_single_function, ONLY: invoke_0_testkern_type" in gen
    assert "CALL invoke_0_testkern_type(f1, f2, m1)" in gen
Beispiel #11
0
 def test_invoke_named_invoke(self):
     ''' Test that we correctly handle a named invoke call where the
     naming string already begins with "invoke_" '''
     alg, _ = generate(
         os.path.join(os.path.dirname(os.path.abspath(__file__)),
                      "test_files", "dynamo0p3",
                      "1.0.5_invoke_named_invoke.f90"),
         api="dynamo0.3")
     gen = str(alg)
     print gen
     assert "USE single_invoke_psy, ONLY: invoke_important" in gen
     assert "CALL invoke_important(a, f1, f2, m1, m2)" in gen
Beispiel #12
0
def test_script_attr_error():
    ''' checks that generator.py raises an appropriate error when a
        script file contains a trans() function which raises an
        attribute error. This is what we previously used to check for
        a script file not containing a trans() function.'''
    with pytest.raises(GenerationError) as excinfo:
        _, _ = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                     "1_single_invoke.f90"),
                        api="dynamo0.3",
                        script_name=os.path.join(BASE_PATH, "dynamo0p3",
                                                 "error_trans.py"))
    assert 'object has no attribute' in str(excinfo.value)
Beispiel #13
0
def test_op_and_scalar_and_qr_derived_type_args():
    ''' Test the case where the operator, scalar and qr arguments to a
    kernel are all supplied by de-referencing derived types. '''
    alg, _ = generate(os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "test_files", "dynamo0p3",
        "10.6.1_operator_no_field_scalar_deref.f90"),
                      api="dynamo0.3")
    gen = str(alg)

    assert ("CALL invoke_0_testkern_operator_nofield_scalar_type("
            "opbox % my_mapping, box % b(1), qr % init_quadrature_symmetrical"
            "(3_i_def, qrl_gauss))" in gen)
Beispiel #14
0
def test_deref_derived_type_args():
    ''' Test the case where a kernel argument is specified as both a
    component of a derived type and as the result of a call to a
    type-bound procedure '''
    alg, _ = generate(os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "test_files", "dynamo0p3",
        "1.6.2_single_invoke_1_int_from_derived_type.f90"),
                      api="dynamo0.3")
    gen = str(alg)
    print(gen)
    assert ("CALL invoke_0(f1, my_obj%iflag, f2, m1, m2, my_obj%get_flag(), "
            "my_obj%get_flag(switch), my_obj%get_flag(int_wrapper%data))"
            in gen)
Beispiel #15
0
def test_script_null_trans_relative():
    ''' checks that generator.py works correctly when the trans()
        function in a valid script file does no transformations (it
        simply passes input to output). In this case the valid
        script file contains no path and must therefore be found via
        the PYTHOPATH path list. '''
    alg1, psy1 = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                       "1_single_invoke.f90"),
                          api="dynamo0.3")
    # set up the python path so that null_trans.py can be found
    os.sys.path.append(os.path.join(BASE_PATH, "dynamo0p3"))
    alg2, psy2 = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                       "1_single_invoke.f90"),
                          api="dynamo0.3", script_name="null_trans.py")
    # remove imported module so we do not affect any following tests
    delete_module("null_trans")
    os.sys.path.pop()
    # we need to remove the first line before comparing output as
    # this line is an instance specific header
    assert '\n'.join(str(alg1).split('\n')[1:]) == \
        '\n'.join(str(alg2).split('\n')[1:])
    assert str(psy1) == str(psy2)
def test_long_line_continuator():
    '''Tests that an input algorithm file with long lines of a type not
       recognised by FortLineLength (assignments in this case), which
       already have continuators to make the code conform to the line
       length limit, does not cause an error.
    '''
    alg, _ = generate(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   "test_files", "dynamo0p3",
                                   "13.2_alg_long_line_continuator.f90"),
                      api="dynamo0.3")
    input_string = str(alg)
    fll = FortLineLength()
    _ = fll.process(input_string)
Beispiel #17
0
def test_script_null_trans():
    ''' checks that generator.py works correctly when the trans()
        function in a valid script file does no transformations (it
        simply passes input to output). In this case the valid
        script file has an explicit path and must therefore exist at
        this location. '''
    alg1, psy1 = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                       "1_single_invoke.f90"),
                          api="dynamo0.3")
    alg2, psy2 = generate(os.path.join(BASE_PATH, "dynamo0p3",
                                       "1_single_invoke.f90"),
                          api="dynamo0.3",
                          script_name=os.path.join(BASE_PATH, "dynamo0p3",
                                                   "null_trans.py"))
    # remove module so we do not affect any following tests
    delete_module("null_trans")
    # we need to remove the first line before comparing output as
    # this line is an instance specific header
    assert '\n'.join(str(alg1).split('\n')[1:]) == \
        '\n'.join(str(alg2).split('\n')[1:])
    assert '\n'.join(str(psy1).split('\n')[1:]) == \
        '\n'.join(str(psy2).split('\n')[1:])
Beispiel #18
0
def test_invalid_kern_naming():
    ''' Check that we raise the expected error if an invalid kernel-renaming
    scheme is supplied. '''
    alg_filename = (os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                 "test_files", "dynamo0p3",
                                 "1_single_invoke.f90"))
    # Simply supplying the wrong value on the command line is picked up
    # by the argparse module so we call generate() directly with an
    # incorrect value
    with pytest.raises(GenerationError) as err:
        _, _ = generate(alg_filename, api="dynamo0.3",
                        kern_naming="not-a-scheme")
    assert "Invalid kernel-renaming scheme supplied" in str(err.value)
    assert "but got 'not-a-scheme'" in str(err.value)
Beispiel #19
0
 def test_named_multi_invokes(self):
     ''' Check that we generate correct code when we have more than one
     named invoke in an Algorithm file '''
     alg, _ = generate(os.path.join(
         BASE_PATH, "3.2_multi_functions_multi_named_invokes.f90"),
                       api="dynamo0.3")
     gen = str(alg)
     assert "USE testkern, ONLY: testkern_type" in gen
     assert "USE testkern_qr, ONLY: testkern_qr_type" in gen
     assert ("USE multi_functions_multi_invokes_psy, ONLY: "
             "invoke_my_first" in gen)
     assert ("USE multi_functions_multi_invokes_psy, ONLY: "
             "invoke_my_second" in gen)
     assert "CALL invoke_my_first(a, f1, f2," in gen
     assert "CALL invoke_my_second(f1, f2, m1, a, m2" in gen
Beispiel #20
0
def test_multi_position_named_invoke():
    ''' Test that we correctly handle a named invoke call that contains
    more than one kernel when the name= clause appears at different
    points in the Invoke argument list '''
    alg, _ = generate(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                   "test_files", "dynamo0p3",
                                   "4.10_multi_position_named_invokes.f90"),
                      api="dynamo0.3")
    gen = str(alg)

    assert "USE multikernel_invokes_7_psy, ONLY: invoke_name_first" in gen
    assert "USE multikernel_invokes_7_psy, ONLY: invoke_name_middle" in gen
    assert "USE multikernel_invokes_7_psy, ONLY: invoke_name_last" in gen
    assert ("CALL invoke_name_first(a, b, istp, rdt, d, e, ascalar, f, c, "
            "g, qr)") in gen
    assert ("CALL invoke_name_middle(a, b, istp, rdt, d, e, ascalar, f, c, "
            "g, qr)") in gen
    assert ("CALL invoke_name_last(a, b, istp, rdt, d, e, ascalar, f, c, "
            "g, qr)") in gen
Beispiel #21
0
def test_script_trans():
    ''' checks that generator.py works correctly when a
        transformation is provided as a script, i.e. it applies the
        transformations correctly. We use loop fusion as an
        example.'''
    from psyclone.parse import parse
    from psyclone.psyGen import PSyFactory
    from psyclone.transformations import LoopFuseTrans
    root_path = os.path.dirname(os.path.abspath(__file__))
    base_path = os.path.join(root_path, "test_files", "dynamo0p3")
    # first loop fuse explicitly (without using generator.py)
    parse_file = os.path.join(base_path, "4_multikernel_invokes.f90")
    _, invoke_info = parse(parse_file, api="dynamo0.3")
    psy = PSyFactory("dynamo0.3").create(invoke_info)
    invoke = psy.invokes.get("invoke_0")
    schedule = invoke.schedule
    # remove unecessary halos between loops. At the moment we have no
    # intra halo analysis so we add them before all loops just in
    # case.
    del schedule.children[4:7]
    loop1 = schedule.children[3]
    loop2 = schedule.children[4]
    trans = LoopFuseTrans()
    schedule.view()
    schedule, _ = trans.apply(loop1, loop2)
    invoke.schedule = schedule
    generated_code_1 = psy.gen
    schedule.view()
    # second loop fuse using generator.py and a script
    _, generated_code_2 = generate(parse_file,
                                   api="dynamo0.3",
                                   script_name=os.path.join(
                                       base_path, "loop_fuse_trans.py"))
    # remove module so we do not affect any following tests
    delete_module("loop_fuse_trans")
    # third - check that the results are the same ...
    assert str(generated_code_1) == str(generated_code_2)
Beispiel #22
0
def test_invalid_api():
    ''' checks that alg_gen raises appropriate error when an invalid
        api is supplied '''
    with pytest.raises(GenerationError):
        generate(os.path.join(BASE_PATH, "dynamo0p1", "algorithm",
                              "1_single_function.f90"), api="invalid")
Beispiel #23
0
def test_non_existant_filename():
    ''' checks that alg_gen raises appropriate error when a
    non-existant filename is supplied '''
    with pytest.raises(IOError):
        generate("non_existant_file.f90")
Beispiel #24
0
''' Script to demonstrate the use on the line wrapping support in PSyclone'''
from __future__ import print_function
from psyclone.generator import generate
from psyclone.line_length import FortLineLength
# long_lines=True checks whether the input fortran conforms to the 132 line
# length limit
ALG, PSY = generate(
    "longlines.f90",
    kernel_path="../../src/psyclone/tests/test_files/dynamo0p3",
    line_length=True)
LINE_LENGTH = FortLineLength()
ALG_STR = LINE_LENGTH.process(str(ALG))
print(ALG_STR)
PSY_STR = LINE_LENGTH.process(str(PSY))
print(PSY_STR)