text:
# This file is a part of TypeDBClient.  License is MIT: https://github.com/Humans-of-Julia/TypeDBClient.jl/blob/main/LICENSE

# Scenario: Relation and role types can be created
@then("relation(marriage) is null: false") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    @expect res !== nothing
end

@then("relation(marriage) get supertype: relation") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    res_relat_super = g.get_supertype(g.as_remote(res, context[:transaction]))
    @expect res_relat_super.label.name == "relation"
end

@then("relation(marriage) get role(husband) is null: false") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "husband")
    @expect role_play !== nothing
end

@then("relation(marriage) get role(wife) is null: false") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "wife")
    @expect role_play !== nothing
end

@then("relation(marriage) get role(husband) get supertype: relation:role") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "husband")
    res_supertype = g.get_supertype(g.as_remote(role_play, context[:transaction]))
    @expect res_supertype == RoleType(g.Label("relation","role"),true)
end

@then("relation(marriage) get role(wife) get supertype: relation:role") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "wife")
    res_supertype = g.get_supertype(g.as_remote(role_play, context[:transaction]))
    @expect res_supertype == RoleType(g.Label("relation","role"),true)
end

@then("relation(marriage) get related roles contain:") do context
    result_contain = _get_related_roles_contain(context, "marriage")
    @expect all(result_contain)
end

#  Scenario: Relation and role types can be deleted
@when("relation(marriage) set relates role: spouse") do context
    g.set_relates(context[:transaction],
        g.Label("","marriage"),
                "spouse")
end

@when("relation(parentship) unset related role: parent") do context
   rel_res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    g.unset_relates(g.as_remote(rel_res, context[:transaction]), "parent")
end

@then("relation(parentship) get related roles do not contain:") do context
    result_contain = _get_related_roles_contain(context, "parentship")
    @expect all(result_contain) === false
end

@then("relation(relation) get role(role) get subtypes do not contain:") do context
    db_contain = [_split_role(db[1]) for db in context.datatable]
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "relation")
    role = g.relation_type_get_relates_for_role_label(g.as_remote(rel, context[:transaction]), "role")
    subtypes_roles = g.get_subtypes(g.as_remote(role, context[:transaction]))
    for i in 1:length(db_contain)
        type = RoleType(g.Label(db_contain[i].first, db_contain[i].second), false)
        @expect !in(type, subtypes_roles)
    end
end

@when("delete relation type: parentship") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "parentship")
    g.delete(g.as_remote(rel, context[:transaction]))
end

@then("relation(parentship) is null: true") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "parentship")
    @expect rel === nothing
end

@then("relation(marriage) unset related role: spouse") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    g.unset_relates(g.as_remote(rel, context[:transaction]), "spouse")
end

@then("relation(marriage) get related roles do not contain:") do context
    result_contain = _get_related_roles_contain(context, "marriage")
    @expect all(result_contain) === false
end

@then("delete relation type: marriage") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    g.delete(g.as_remote(rel, context[:transaction]))
end

@then("relation(marriage) is null: true") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    @expect rel === nothing
end

# Scenario: Relation types that have instances cannot be deleted
@then("delete relation type: marriage; throws exception") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    try
        g.delete(g.as_remote(rel, context[:transaction]))
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Role types that have instances cannot be deleted
@then("relation(marriage) unset related role: wife; throws exception") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    try
        g.unset_relates(g.as_remote(rel, context[:transaction]), "wife")
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(marriage) unset related role: husband") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    g.unset_relates(g.as_remote(rel, context[:transaction]), "husband")
end

# Scenario: Relation and role types can change labels
@then("relation(parentship) get label: parentship") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    @expect rel.label.name == "parentship"
end

@then("relation(parentship) get role(parent) get label: parent") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "parent")
    @expect role_play.label.name == "parent"
end

@then("relation(parentship) get role(child) get label: child") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    @expect role_play.label.name == "child"
end

@then("relation(parentship) set label: marriage") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    g.set_label(g.as_remote(rel, context[:transaction]), "marriage")
end

@then("relation(marriage) get role(parent) set label: husband") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "parent")
    g.set_label(g.as_remote(role_play, context[:transaction]), "husband")
end

@then("relation(marriage) get role(child) set label: wife") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    g.set_label(g.as_remote(role_play, context[:transaction]), "wife")
end

@then("relation(marriage) get role(parent) is null: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "parent")
    @expect role_play === nothing
end

@then("relation(marriage) get role(child) is null: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    @expect role_play === nothing
end

@then("relation(marriage) get label: marriage") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    @expect rel.label.name == "marriage"
end

@then("relation(marriage) get role(husband) get label: husband") do context
    res = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "husband")
    @expect role_play.label.name == "husband"
end

@then("relation(marriage) get role(wife) get label: wife") do context
    res = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "wife")
    @expect role_play.label.name == "wife"
end

@when("relation(marriage) set label: employment") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    g.set_label(g.as_remote(rel, context[:transaction]), "employment")
end

@then("relation(employment) is null: false") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    @expect rel !== nothing
end

@when("relation(employment) get role(husband) set label: employee") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "husband")
    g.set_label(g.as_remote(role_play, context[:transaction]), "employee")
end

@when("relation(employment) get role(wife) set label: employer") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "wife")
    g.set_label(g.as_remote(role_play, context[:transaction]), "employer")
end

@then("relation(employment) get role(husband) is null: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "husband")
    @expect role_play === nothing
end

@then("relation(employment) get role(wife) is null: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "wife")
    @expect role_play === nothing
end

@then("relation(employment) get label: employment") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    @expect res.label.name == "employment"
end

@then("relation(employment) get role(employee) get label: employee") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "employee")
    @expect role_play.label.name == "employee"
end

@then("relation(employment) get role(employer) get label: employer") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "employment")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "employer")
    @expect role_play.label.name == "employer"
end

# Scenario: Relation and role types can be set to abstract
@when("relation(marriage) set abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    g.set_abstract(g.as_remote(res, context[:transaction]))
end

@then("relation(marriage) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    result = g.is_abstract(g.as_remote(res, context[:transaction]))
    @expect result
end

@then("relation(marriage) get role(husband) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "husband")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result
end

@then("relation(marriage) get role(wife) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "wife")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result
end

@then("relation(marriage) create new instance; throws exception") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    try
        g.create(g.as_remote(res, context[:transaction]))
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(parentship) is abstract: false") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    result = g.is_abstract(g.as_remote(res, context[:transaction]))
    @expect result === false
end

@then("relation(parentship) get role(parent) is abstract: false") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "parent")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result === false
end

@then("relation(parentship) set abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    g.set_abstract(g.as_remote(res, context[:transaction]))
end

@then("relation(parentship) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    result = g.is_abstract(g.as_remote(res, context[:transaction]))
    @expect result
end

@then("relation(parentship) get role(parent) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "parent")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result
end

@then("relation(parentship) get role(child) is abstract: false") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result === false
end

@then("elation(parentship) get role(child) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result
end

@then("relation(parentship) get role(child) is abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    result = g.is_abstract(g.as_remote(role_play, context[:transaction]))
    @expect result
end

@then("relation(parentship) create new instance; throws exception") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "parentship")
    try
        g.create(g.as_remote(res, context[:transaction]))
     catch ex
        @expect ex !== nothing
     end
end

# Scenario: Relation types must have at least one role in order to commit, unless they are abstract
@when("put relation type: connection") do context
    g.put(ConceptManager(context[:transaction]),
            RelationType,
            "connection")
end

@when("relation(connection) set abstract: true") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "connection")
    g.set_abstract(g.as_remote(rel, context[:transaction]))
end

# Scenario: Relation and role types can be subtypes of other relation and role types
@then("relation(fathership) get supertype: parentship") do context
    rel = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "fathership")
    res = g.get_supertype(g.as_remote(rel, context[:transaction]))
    @expect res.label.name == "parentship"
end

@then("relation(fathership) get role(father) get supertype: parentship:parent") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "fathership")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "father")
    res_supertype = g.get_supertype(g.as_remote(role_play, context[:transaction]))
    @expect res_supertype == RoleType(g.Label("parentship","parent"),false)
end

@then("relation(fathership) get role(child) get supertype: relation:role") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "fathership")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "child")
    res_supertype = g.get_supertype(g.as_remote(role_play, context[:transaction]))
    @expect res_supertype == RoleType(g.Label("relation","role"),true)
end

@then("relation(fathership) get supertypes contain:") do context
    res_contain = _supertypes_contain(context, RelationType, "fathership")
    @expect all(res_contain)
end

@then("relation(fathership) get role(father) get supertypes contain:") do context
    res_contain = _supertypes_contain(context, RoleType, "fathership", "father")
    @expect all(res_contain)
end

@then("relation(fathership) get role(child) get supertypes contain:") do context
    res_contain = _supertypes_contain(context, RoleType, "fathership", "child")
    @expect all(res_contain)
end

@then("relation(parentship) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RelationType, "parentship")
    @expect all(res_contain)
end

@then("relation(parentship) get role(parent) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RoleType, "parentship", "parent")
    @expect all(res_contain)
end

@then("relation(parentship) get role(child) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RoleType, "parentship", "child")
    @expect all(res_contain)
end

@then("relation(relation) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RelationType, "relation")
    @expect all(res_contain)
end

@then("relation(relation) get role(role) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RoleType, "relation", "role")
    @expect all(res_contain)
end

@when("put relation type: father-son") do context
    res = g.put(context[:cm], RelationType, "father-son")
end

@when("relation(father-son) set supertype: fathership") do context
    _set_supertype_for_type(context, RelationType, "father-son", "fathership")
end

@when("relation(father-son) set relates role: son as child") do context
    g.set_relates(context[:transaction],
        g.Label("","father-son"),
                "son",
                "child")
end

@when("relation(father-son) get supertype: fathership") do context
    rel = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "father-son")
    res = g.get_supertype(g.as_remote(rel, context[:transaction]))
    @expect res.label.name == "fathership"
end

@then("relation(father-son) get role(father) get supertype: parentship:parent") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "father-son")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "father")
    res_supertype = g.get_supertype(g.as_remote(role_play, context[:transaction]))
    @expect res_supertype == RoleType(g.Label("parentship","parent"),true)
end

@then("relation(father-son) get role(son) get supertype: parentship:child") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "father-son")
    role_play = g.relation_type_get_relates_for_role_label(g.as_remote(res, context[:transaction]), "son")
    res_supertype = g.get_supertype(g.as_remote(role_play, context[:transaction]))
    @expect res_supertype == RoleType(g.Label("parentship","child"),true)
end

@then("relation(father-son) get supertypes contain:") do context
    res_contain = _supertypes_contain(context, RelationType, "father-son")
    @expect all(res_contain)
end

@then("relation(father-son) get role(father) get supertypes contain:") do context
    res_contain = _supertypes_contain(context, RoleType, "father-son", "father")
    @expect all(res_contain)
end

@then("relation(father-son) get role(son) get supertypes contain:") do context
    res_contain = _supertypes_contain(context, RoleType, "father-son", "son")
    @expect all(res_contain)
end

@then("relation(fathership) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RelationType, "fathership")
    @expect all(res_contain)
end

@then("relation(fathership) get role(father) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RoleType, "fathership", "father")
    @expect all(res_contain)
end

@then("relation(fathership) get role(child) get subtypes contain:") do context
    res_contain = _subtypes_contain(context, RoleType, "fathership", "child")
    @expect all(res_contain)
end

# Scenario: Relation types cannot subtype itself
@then("relation(marriage) set supertype: marriage; throws exception") do context
    res = g.get(ConceptManager(context[:transaction]),
                RelationType,
                "marriage")
    try
        g.set_supertype(g.as_remote(res, context[:transactino]), "marriage")
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types can inherit related role types
@then("relation(fathership) get related roles contain:") do context
    result_contain = _get_related_roles_contain(context, "fathership")
    @expect all(result_contain)
end

@then("relation(mothership) get related roles contain:") do context
    result_contain = _get_related_roles_contain(context, "mothership")
    @expect all(result_contain)
end

# Scenario: Relation types can override inherited related role types
@then("relation(mothership) get related roles do not contain:") do context
    result_contain = _get_related_roles_contain(context, "mothership")
    @expect all(result_contain) === false
end

# Scenario: Relation types cannot redeclare inherited related role types
@then("relation(fathership) set relates role: parent; throws exception") do context
    try
        g.set_relates(context[:transaction],
            g.Label("","fathership"),
                    "parent")
     catch ex
        @expect ex !== nothing
     end
end

@then("relation(fathership) get related roles do not contain:") do context
    result_contain = _get_related_roles_contain(context, "fathership")
    @expect all(result_contain) === false
end

# Scenario: Relation types cannot override declared related role types
@then("relation(parentship) set relates role: father as parent; throws exception") do context
    try
        g.set_relates(context[:transaction],
            g.Label("","parentship"),
                    "father",
                    "parent")
     catch ex
        @expect ex !== nothing
     end
end

# Scenario: Relation types can have keys
@then("relation(marriage) get owns key types contain:") do context
    res = _get_owns_contain(context, RelationType, "marriage", true)
    @expect all(res)
end

# Scenario: Relation types can unset keys
@when("put attribute type: certificate, with value type: string") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "certificate",
            VALUE_TYPE.STRING)
end

@when("relation(marriage) set owns key type: certificate") do context
    g.con.entity_set_owns(g.RelationType ,"marriage", "certificate", context[:transaction], true)
end

@when("relation(marriage) unset owns key type: license") do context
    attr_country_name = g.get(ConceptManager(context[:transaction]), RelationType, "marriage")
    attr_country_code = g.get(ConceptManager(context[:transaction]), AttributeType, "license")
    g.unset_owns(g.as_remote(attr_country_name, context[:transaction]),
                    attr_country_code)
end

@then("relation(marriage) get owns key types do not contain:") do context
    res = _get_owns_contain(context, RelationType, "marriage", true)
    @expect all(res) === false
end

@when("relation(marriage) unset owns key type: certificate") do context
    attr_country_name = g.get(ConceptManager(context[:transaction]), RelationType, "marriage")
    attr_country_code = g.get(ConceptManager(context[:transaction]), AttributeType, "certificate")
    g.unset_owns(g.as_remote(attr_country_name, context[:transaction]),
                    attr_country_code)
end

# Scenario: Relation types can have keys of all keyable attributes
@when("put attribute type: is-permanent, with value type: boolean") do context
    g.put(context[:cm], AttributeType, "is-permanent", VALUE_TYPE.BOOLEAN)
end

@when("put attribute type: contract-years, with value type: long") do context
    g.put(context[:cm], AttributeType, "contract-years", VALUE_TYPE.LONG)
end

@when("put attribute type: salary, with value type: double") do context
    g.put(context[:cm], AttributeType, "salary", VALUE_TYPE.DOUBLE)
end

@when("put attribute type: start-date, with value type: datetime") do context
    g.put(context[:cm], AttributeType, "start-date", VALUE_TYPE.DATETIME)
end

@when("put relation type: employment") do context
    g.put(context[:cm], RelationType, "employment")
end

@when("relation(employment) set owns key type: contract-years") do context
    g.con.entity_set_owns(g.RelationType ,"employment", "contract-years", context[:transaction], true)
end

@when("relation(employment) set owns key type: reference") do context
    g.con.entity_set_owns(g.RelationType ,"employment", "reference", context[:transaction], true)
end

@when("relation(employment) set owns key type: start-date") do context
    g.con.entity_set_owns(g.RelationType ,"employment", "start-date", context[:transaction], true)
end

@then("relation(employment) set owns key type: is-permanent; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,"employment", "is-permanent", context[:transaction], true)
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(employment) set owns key type: salary; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,"employment", "salary", context[:transaction], true)
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types can have attributes
@when("put attribute type: religion, with value type: string") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "religion",
            VALUE_TYPE.STRING)
end

@when("relation(marriage) set owns attribute type: religion") do context
    g.con.entity_set_owns(g.RelationType ,"marriage", "religion", context[:transaction], false)
end

@then("relation(marriage) get owns attribute types contain:") do context
    res = _get_owns_contain(context, RelationType, "marriage", false)
    @expect all(res)
end

# Scenario: Relation types can unset attributes
@when("relation(marriage) unset owns attribute type: religion") do context
    _thing_type_unset_type(context, RelationType, "marriage", AttributeType, "religion")
end

@then("relation(marriage) get owns attribute types do not contain:") do context
    res = _get_owns_contain(context, RelationType, "marriage", false)
    @expect all(res) === false
end

@when("relation(marriage) unset owns attribute type: date") do context
    _thing_type_unset_type(context, RelationType, "marriage", AttributeType, "date")
end

# Scenario: Relation types can inherit keys and attributes
@when("put attribute type: employment-reference, with value type: string") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "employment-reference",
            VALUE_TYPE.STRING)
end

@when("put attribute type: employment-hours, with value type: long") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "employment-hours",
            VALUE_TYPE.LONG)
end

@when("put attribute type: contractor-reference, with value type: string") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "contractor-reference",
            VALUE_TYPE.STRING)
end

@when("put attribute type: contractor-hours, with value type: long") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "contractor-hours",
            VALUE_TYPE.LONG)
end

@when("relation(employment) set relates role: employee") do context
    g.set_relates(context[:transaction],
        g.Label("","employment"),
                "employee")
end

@when("relation(employment) set relates role: employer") do context
    g.set_relates(context[:transaction],
        g.Label("","employment"),
                "employer")
end

@when("relation(employment) set owns key type: employment-reference") do context
    g.con.entity_set_owns(g.RelationType ,"employment", "employment-reference", context[:transaction], true)
end

@when("relation(employment) set owns attribute type: employment-hours") do context
    g.con.entity_set_owns(g.RelationType ,"employment", "employment-hours", context[:transaction], false)
end

@when("put relation type: contractor-employment") do context
    g.put(ConceptManager(context[:transaction]),
            RelationType,
            "contractor-employment")
end

@when("relation(contractor-employment) set supertype: employment") do context
    _set_supertype_for_type(context, RelationType, "contractor-employment", "employment")
end

@when("relation(contractor-employment) set owns key type: contractor-reference") do context
    g.con.entity_set_owns(g.RelationType ,"contractor-employment", "contractor-reference", context[:transaction], true)
end

@when("relation(contractor-employment) set owns attribute type: contractor-hours") do context
    g.con.entity_set_owns(g.RelationType ,"contractor-employment", "contractor-hours", context[:transaction], false)
end

@then("relation(contractor-employment) get owns key types contain:") do context
    res = _get_owns_contain(context, RelationType, "contractor-employment", true)
    @expect all(res)
end

@then("relation(contractor-employment) get owns attribute types contain:") do context
    res = _get_owns_contain(context, RelationType, "contractor-employment", false)
    @expect all(res)
end

@when("put attribute type: parttime-reference, with value type: string") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "parttime-reference",
            VALUE_TYPE.STRING)
end

@when("put attribute type: parttime-hours, with value type: long") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "parttime-hours",
            VALUE_TYPE.LONG)
end

@when("put relation type: parttime-employment") do context
    g.put(context[:cm], RelationType, "parttime-employment")
end

@when("relation(parttime-employment) set supertype: contractor-employment") do context
    _set_supertype_for_type(context, RelationType, "parttime-employment", "contractor-employment")
end

@when("relation(parttime-employment) set owns key type: parttime-reference") do context
    g.con.entity_set_owns(g.RelationType ,"parttime-employment", "parttime-reference", context[:transaction], true)
end

@when("relation(parttime-employment) set owns attribute type: parttime-hours") do context
    g.con.entity_set_owns(g.RelationType ,"parttime-employment", "parttime-hours", context[:transaction], false)
end

@then("relation(parttime-employment) get owns key types contain:") do context
    res = _get_owns_contain(context, RelationType, "parttime-employment", true)
    @expect all(res)
end

@then("relation(parttime-employment) get owns attribute types contain:") do context
    res = _get_owns_contain(context, RelationType, "parttime-employment", false)
    @expect all(res)
end

# Scenario: Relation types can inherit keys and attributes that are subtypes of each other
@when("attribute(employment-reference) set abstract: true") do context
    attr = g.get(context[:cm], AttributeType, "employment-reference")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

@when("attribute(employment-hours) set abstract: true") do context
    attr = g.get(context[:cm], AttributeType, "employment-hours")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

@when("attribute(contractor-reference) set abstract: true") do context
    attr = g.get(context[:cm], AttributeType, "contractor-reference")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

@when("attribute(contractor-reference) set supertype: employment-reference") do context
    _set_supertype_for_type(context, AttributeType, "contractor-reference", "employment-reference")
end

@when("attribute(contractor-hours) set abstract: true") do context
    attr = g.get(context[:cm], AttributeType, "contractor-hours")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

@when("attribute(contractor-hours) set supertype: employment-hours") do context
    _set_supertype_for_type(context, AttributeType, "contractor-hours", "employment-hours")
end

@when("relation(employment) set abstract: true") do context
    attr = g.get(context[:cm], RelationType, "employment")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

@when("relation(contractor-employment) set abstract: true") do context
    attr = g.get(context[:cm], RelationType, "contractor-employment")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

@when("attribute(parttime-reference) set supertype: contractor-reference") do context
    _set_supertype_for_type(context, AttributeType, "parttime-reference", "contractor-reference")
end

@when("attribute(parttime-hours) set supertype: contractor-hours") do context
    _set_supertype_for_type(context, AttributeType, "parttime-hours", "contractor-hours")
end

@when("relation(parttime-employment) set abstract: true") do context
    attr = g.get(context[:cm], RelationType, "parttime-employment")
    g.set_abstract(g.as_remote(attr, context[:transaction]))
end

# Scenario: Relation types can override inherited keys and attributes
@when("relation(contractor-employment) set owns key type: contractor-reference as employment-reference") do context
    g.con.entity_set_owns(g.RelationType ,
            "contractor-employment",
            "contractor-reference",
            context[:transaction],
            true,
            "employment-reference")
end

@when("relation(contractor-employment) set owns attribute type: contractor-hours as employment-hours") do context
    g.con.entity_set_owns(g.RelationType ,
            "contractor-employment",
            "contractor-hours",
            context[:transaction],
            false,
            "employment-hours")
end

@then("relation(contractor-employment) get owns key types do not contain:") do context
    res = _get_owns_contain(context, RelationType, "contractor-employment", true)
    @expect all(res) === false
end

@then("relation(contractor-employment) get owns attribute types do not contain:") do context
    res = _get_owns_contain(context, RelationType, "contractor-employment", false)
    @expect all(res) === false
end

@when("relation(parttime-employment) set relates role: parttime-employer as employer") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-employment"),
                "parttime-employer",
                "employer")
end

@when("relation(parttime-employment) set relates role: parttime-employee as employee") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-employment"),
                "parttime-employee",
                "employee")
end

@when("relation(parttime-employment) set owns key type: parttime-reference as contractor-reference") do context
    g.con.entity_set_owns(g.RelationType ,
            "parttime-employment",
            "parttime-reference",
            context[:transaction],
            true,
            "contractor-reference")
end

@when("relation(parttime-employment) set owns attribute type: parttime-hours as contractor-hours") do context
    g.con.entity_set_owns(g.RelationType ,
            "parttime-employment",
            "parttime-hours",
            context[:transaction],
            false,
            "contractor-hours")
end

@then("relation(parttime-employment) get owns key types do not contain:") do context
    res = _get_owns_contain(context, RelationType, "parttime-employment", true)
    @expect all(res) === false
end

# Scenario: Relation types can override inherited attributes as keys
@when("relation(employment) set owns attribute type: employment-reference") do context
    g.con.entity_set_owns(g.RelationType ,
            "employment",
            "employment-reference",
            context[:transaction],
            false)
end

@when("relation(contractor-employment) set relates role: contractor-employer as employer") do context
    g.set_relates(context[:transaction],
        g.Label("","contractor-employment"),
                "contractor-employer",
                "employer")
end

@when("relation(contractor-employment) set relates role: contractor-employee as employee") do context
    g.set_relates(context[:transaction],
        g.Label("","contractor-employment"),
                "contractor-employee",
                "employee")
end

# Scenario: Relation types can redeclare keys as attributes
@when("relation(marriage) set owns key type: date") do context
    g.con.entity_set_owns(g.RelationType , "marriage", "date", context[:transaction], true)
end

@then("relation(marriage) set owns attribute type: license") do context
    g.con.entity_set_owns(g.RelationType , "marriage", "license", context[:transaction], false)
end

# Scenario: Relation types cannot redeclare inherited keys and attributes
@then("relation(contractor-employment) set owns key type: employment-reference; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "contractor-employment",
                "employment-reference",
                context[:transaction],
                true)
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(contractor-employment) set owns attribute type: employment-hours; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "contractor-employment",
                "employment-hours",
                context[:transaction],
                false)
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot redeclare inherited key attribute types
@then("relation(parttime-employment) set owns key type: employment-reference; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "parttime-employment",
                "employment-reference",
                context[:transaction],
                true)
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(parttime-employment) set owns key type: contractor-reference; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "parttime-employment",
                "contractor-reference",
                context[:transaction],
                true)
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot redeclare inherited owns attribute types
@then("relation(parttime-employment) set owns attribute type: employment-hours; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "parttime-employment",
                "employment-hours",
                context[:transaction],
                false)
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot redeclare overridden owns attribute types
@then("relation(parttime-employment) set owns attribute type: contractor-hours; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "parttime-employment",
                "contractor-hours",
                context[:transaction],
                false)
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot override declared keys and attributes
@when("put attribute type: social-security-number, with value type: string") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "social-security-number",
            VALUE_TYPE.STRING)
end

@when("attribute(social-security-number) set supertype: reference") do context
    _set_supertype_for_type(context, AttributeType, "social-security-number", "reference")
end

@when("put attribute type: hours, with value type: long") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "hours",
            VALUE_TYPE.LONG)
end

@when("attribute(hours) set abstract: true") do context
    res = g.get(ConceptManager(context[:transaction]),
                AttributeType,
                "hours")
    g.set_abstract(g.as_remote(res, context[:transaction]))
end

@when("put attribute type: max-hours, with value type: long") do context
    g.put(ConceptManager(context[:transaction]),
            AttributeType,
            "max-hours",
            VALUE_TYPE.LONG)
end

@when("attribute(max-hours) set supertype: hours") do context
    _set_supertype_for_type(context, AttributeType, "max-hours", "hours")
end

@when("relation(employment) set owns attribute type: hours") do context
    g.con.entity_set_owns(g.RelationType ,"employment", "hours", context[:transaction], false)
end

@then("relation(employment) set owns key type: social-security-number as reference; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "employment",
                "social-security-number",
                context[:transaction],
                false)
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(employment) set owns attribute type: max-hours as hours; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "employment",
                "max-hours",
                context[:transaction],
                false,
                "hours")
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot override inherited keys as attributes
@then("relation(contractor-employment) set owns attribute type: contractor-reference as employment-reference; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "contractor-employment",
                "contractor-reference",
                context[:transaction],
                false,
                "employment-reference")
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot override inherited keys and attributes other than with their subtypes
@then("relation(contractor-employment) set owns key type: contractor-reference as employment-reference; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "contractor-employment",
                "contractor-reference",
                context[:transaction],
                true,
                "employment-reference")
    catch ex
        @expect ex !== nothing
    end
end

@then("relation(contractor-employment) set owns attribute type: contractor-hours as employment-hours; throws exception") do context
    try
        g.con.entity_set_owns(g.RelationType ,
                "contractor-employment",
                "contractor-hours",
                context[:transaction],
                true,
                "employment-hours")
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types can play role types
@when("put relation type: locates") do  context
    g.put(context[:cm], RelationType, "locates")
end

@when("relation(locates) set relates role: location") do context
    g.set_relates(context[:transaction],
        g.Label("","locates"),
                "location")
end

@when("relation(locates) set relates role: located") do context
    g.set_relates(context[:transaction],
        g.Label("","locates"),
                "located")
end

# Scenario: Relation types can unset playing role types
@then("relation(marriage) unset plays role: locates:located") do context
    role = RoleType(g.Label("locates","located"), false)
    attr = g.get(ConceptManager(context[:transaction]),
                    RelationType,
                    "marriage")

    g.unset_plays(g.as_remote(attr, context[:transaction]),role)
end

@then("relation(marriage) get playing roles do not contain:") do context
    res = _get_playing_roles_contain("marriage", RelationType, context)
    @expect all(res) === false
end

@when("relation(marriage) unset plays role: organises:organised") do context
    role = RoleType(g.Label("organises","organised"), false)
    attr = g.get(context[:cm], RelationType, "marriage")

    g.unset_plays(g.as_remote(attr, context[:transaction]),role)
end

# Scenario: Relation types can inherit playing role types
@when("relation(locates) set relates role: locating") do context
    g.set_relates(context[:transaction],
        g.Label("","locates"),
                "locating")
end

@when("put relation type: contractor-locates") do context
    g.put(ConceptManager(context[:transaction]),
            RelationType,
            "contractor-locates")
end

@when("relation(contractor-locates) set relates role: contractor-locating") do context
    g.set_relates(context[:transaction],
        g.Label("","contractor-locates"),
                "contractor-locating")
end

@when("relation(contractor-locates) set relates role: contractor-located") do context
    g.set_relates(context[:transaction],
        g.Label("","contractor-locates"),
                "contractor-located")
end

@when("relation(employment) set plays role: locates:located") do context
    ent_pers = g.get(context[:cm], RelationType, "employment")
    g.set_plays(g.as_remote(ent_pers, context[:transaction]), g.RoleType(g.Label("locates", "located"),false))
end

@when("relation(contractor-employment) set plays role: contractor-locates:contractor-located") do context
    ent_pers = g.get(context[:cm], RelationType, "contractor-employment")
    g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                    g.RoleType(g.Label("contractor-locates",
                            "contractor-located"),
                            false))
end

@then("relation(contractor-employment) get playing roles contain:") do context
    res = _get_playing_roles_contain("contractor-employment", RelationType, context)
    @expect all(res)
end

@when("put relation type: parttime-locates") do context
    g.put(ConceptManager(context[:transaction]),
            RelationType,
            "parttime-locates")
end

@when("relation(parttime-locates) set relates role: parttime-locating") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-locates"),
                "parttime-locating")
end

@when("relation(parttime-locates) set relates role: parttime-located") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-locates"),
                "parttime-located")
end

@when("relation(parttime-employment) set relates role: parttime-employer") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-employment"),
                "parttime-employer")
end

@when("relation(parttime-employment) set relates role: parttime-employee") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-employment"),
                "parttime-employee")
end

@when("relation(parttime-employment) set plays role: parttime-locates:parttime-located") do context
    ent_pers = g.get(context[:cm], RelationType, "parttime-employment")
    g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                            g.RoleType(g.Label("parttime-locates"
                                    , "parttime-located"),false))
end

@then("relation(parttime-employment) get playing roles contain:") do context
    res = _get_playing_roles_contain("parttime-employment", RelationType, context)
    @expect all(res)
end

@when("relation(contractor-locates) set supertype: locates") do context
    _set_supertype_for_type(context, RelationType, "contractor-locates", "locates")
end

@when("relation(contractor-locates) set relates role: contractor-locating as locating") do context
    g.set_relates(context[:transaction],
        g.Label("","contractor-locates"),
                "contractor-locating")
end

@when("relation(contractor-locates) set relates role: contractor-located as located") do context
    g.set_relates(context[:transaction],
        g.Label("","contractor-locates"),
                "contractor-located",
                "located")
end

@when("relation(parttime-locates) set supertype: contractor-locates") do context
    _set_supertype_for_type(context, RelationType, "parttime-locates", "contractor-locates")
end

@when("relation(parttime-locates) set relates role: parttime-locating as contractor-locating") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-locates"),
                "parttime-locating",
                "contractor-locating")
end

@when("relation(parttime-locates) set relates role: parttime-located as contractor-located") do context
    g.set_relates(context[:transaction],
        g.Label("","parttime-locates"),
                "parttime-located",
                "contractor-located")
end

# Scenario: Relation types can override inherited playing role types
@when("relation(contractor-employment) set plays role: contractor-locates:contractor-located as locates:located") do context
    ent_pers = g.get(context[:cm], RelationType, "contractor-employment")
    g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                    g.RoleType(g.Label("contractor-locates",
                            "contractor-located"),
                            false),
                    g.RoleType(g.Label("locates",
                            "located")
                            ,false))
end

@then("relation(contractor-employment) get playing roles do not contain:") do context
    res = _get_playing_roles_contain("contractor-employment", RelationType, context)
    @expect all(res) === false
end

@when("relation(parttime-employment) set plays role: parttime-locates:parttime-located as contractor-locates:contractor-located") do context
    ent_pers = g.get(context[:cm], RelationType, "parttime-employment")
    g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                    g.RoleType(g.Label("parttime-locates",
                            "parttime-located"),
                            false),
                    g.RoleType(g.Label("contractor-locates",
                            "contractor-located")
                            ,false))
end

@then("relation(parttime-employment) get playing roles do not contain:") do context
    res = _get_playing_roles_contain("parttime-employment", RelationType, context)
    @expect all(res) === false
end

@when("relation(parttime-employment) set plays role: locates:located; throws exception") do context
    ent_pers = g.get(context[:cm], RelationType, "parttime-employment")
    try
        g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                        g.RoleType(g.Label("locates",
                                "located"),
                                false))
    catch ex
        @expect ex !== nothing
    end
end

@when("relation(parttime-employment) set plays role: contractor-locates:contractor-located; throws exception") do context
    ent_pers = g.get(context[:cm], RelationType, "parttime-employment")
    try
        g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                        g.RoleType(g.Label("contractor-locates",
                                "contractor-located"),
                                false))
    catch ex
        @expect ex !== nothing
    end
end

# Scenario: Relation types cannot override declared playing role types
@when("put relation type: employment-locates") do context
    g.put(context[:cm], RelationType, "employment-locates")
end

@when("relation(employment-locates) set supertype: locates") do context
    _set_supertype_for_type(context, RelationType, "employment-locates", "locates")
end

@when("relation(employment-locates) set relates role: employment-locating as locating") do context
    g.set_relates(context[:transaction],
        g.Label("","employment-locates"),
                "employment-locating",
                "locating")
end

@when("relation(employment-locates) set relates role: employment-located as located") do context
    g.set_relates(context[:transaction],
        g.Label("","employment-locates"),
                "employment-located",
                "located")
end

@when("relation(employment) set plays role: employment-locates:employment-located as locates:located; throws exception") do context
    ent_pers = g.get(context[:cm], RelationType, "employment")
    try
        g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                        g.RoleType(g.Label("employment-locates",
                                "employment-located"),
                                false),
                        g.RoleType(g.Label("locates",
                                "located"),
                                false))
    catch ex
        @expect ex !== nothing
    end
end

@when("relation(contractor-employment) set plays role: contractor-locates:contractor-located as locates:located; throws exception") do context
    ent_pers = g.get(context[:cm], RelationType, "contractor-employment")
    try
        g.set_plays(g.as_remote(ent_pers, context[:transaction]),
                        g.RoleType(g.Label("contractor-locates",
                                "contractor-located"),
                                false),
                        g.RoleType(g.Label("locates",
                                "located"),
                                false))
    catch ex
        @expect ex !== nothing
    end
end


text:
# test suite that can be used for all packages inheriting from GPUArrays
#
# use this by either calling `test`, or inspecting the dictionary `tests`

module TestSuite

export supported_eltypes

using GPUArrays

using LinearAlgebra
using Random
using Test

using Adapt
using FillArrays

struct ArrayAdaptor{AT} end
Adapt.adapt_storage(::ArrayAdaptor{AT}, xs::AbstractArray) where {AT} = AT(xs)

function compare(f, AT::Type{<:AbstractGPUArray}, xs...; kwargs...)
    # copy on the CPU, adapt on the GPU, but keep Ref's
    cpu_in = map(x -> isa(x, Base.RefValue) ? x[] : deepcopy(x), xs)
    gpu_in = map(x -> isa(x, Base.RefValue) ? x[] : adapt(ArrayAdaptor{AT}(), x), xs)

    cpu_out = f(cpu_in...; kwargs...)
    gpu_out = f(gpu_in...; kwargs...)

    if cpu_out isa Tuple && gpu_out isa Tuple
        all(zip(cpu_out,gpu_out)) do (cpu, gpu)
            collect(cpu) ≈ collect(gpu)
        end
    else
        collect(cpu_out) ≈ collect(gpu_out)
    end
end

function compare(f, AT::Type{<:Array}, xs...; kwargs...)
    # no need to actually run this tests: we have nothing to compoare against,
    # and we'll run it on a CPU array anyhow when comparing to a GPU array.
    #
    # this method exists so that we can at least run the test suite with Array,
    # and make sure we cover other tests (that don't call `compare`) too.
    return true
end

function supported_eltypes()
    (Float32, Float64, Int32, Int64, ComplexF32, ComplexF64)
end

# list of tests
const tests = Dict()
macro testsuite(name, ex)
    safe_name = lowercase(replace(name, " "=>"_"))
    fn = Symbol("test_$(safe_name)")
    quote
        $(esc(fn))(AT) = $(esc(ex))(AT)

        @assert !haskey(tests, $name)
        tests[$name] = $fn
    end
end

include("testsuite/construction.jl")
include("testsuite/gpuinterface.jl")
include("testsuite/indexing.jl")
include("testsuite/io.jl")
include("testsuite/base.jl")
#include("testsuite/vector.jl")
include("testsuite/reductions.jl")
include("testsuite/broadcasting.jl")
include("testsuite/linalg.jl")
include("testsuite/math.jl")
include("testsuite/random.jl")
include("testsuite/uniformscaling.jl")
include("testsuite/statistics.jl")

"""
Runs the entire GPUArrays test suite on array type `AT`
"""
function test(AT::Type)
    for (name, fun) in tests
        code = quote
            $fun($AT)
        end
        @eval @testset $name $code
    end
end

end

ext: jl


text:
module Utils

type GeoLoc
    lat :: Float64
    lon :: Float64

    GeoLoc(lat,lon) = new(lat, lon)
end

function show(io :: IO, gl :: GeoLoc)
    print("GL($gl.lat, $gl.lon)")
end

function parse_geolocation(s::String)
    lat, lon = map(x -> float(strip(x)), split(s, ","))
    return GeoLoc(lat, lon)
end

end


text:
using MaxPlus

function f(n::Int64)
  A = rand(n,n);
  @time y = A * A;
end

function g(n::Int64)
  A = mparray(rand(n,n));
  @time y = A * A;
end

# Tested on Scilab 4.4.1 and Julia 0.4 and 1.0.3 downloaded "as it"
# (meaning I did not compile sources). Therefore I guess there is
# no Cuda and no OpenBlas activated.

# Debian 10 amd64. AMD Ryzen 1800x.
         # Julia 1.0.3         # Scicoslab    # Julia 0.4
f(400);  # 0.0018 seconds      0.033596       0.005923 seconds
f(800);  # 0.012382 seconds    0.214737       0.016760 seconds
f(1600); # 0.052756 seconds    2.218538       0.079267 seconds

g(400);  # 0.088829 seconds    0.177505       0.250052 seconds
g(800);  # 0.674794 seconds    1.4063         1.930686 seconds
g(1600); # 5.288377 seconds    14.655486      15.462906 seconds

using Plots
x=[4; 8; 16];
ju04=[0.005923; 0.016760; 0.079267];
ju103=[0.0018; 0.012; 0.05];
sci=[0.033596; 0.214737; 2.218538];
plot(x, [ju04, ju103, sci], title="standard + dense", label=["julia 0.4", "Julia 1.0.3", "ScicosLab"])

mpju04=[0.250052; 1.930686; 15.462906];
mpju103=[0.088829; 0.674794; 5.288377];
mpsci=[0.177505; 1.4063; 14.655486];
plot(x, [mpju04, mpju103, mpsci], title="maxplus + dense", label=["julia 0.4", "Julia 1.0.3", "ScicosLab"])

plot(x, [ju103, mpju103], title="julia 1.0.3 maxplus + dense", label=["normal", "maxplus"])

max_stars_repo_name: Lecrapouille/BacASable

max_issues_repo_name: Lecrapouille/BacASable

max_forks_repo_name: Lecrapouille/BacASable


text:
include("rules/schema.jl")
using JSON
mutable struct schema
  execute::Function
end

function GetOperation(document::Node,operationName::String)

  operation=extract_operation(operationName)
  vi= Visitante(document)
  vi.visitante(operation)
  return operation
end
"""
    Schema(_schema::String, resolvers::Dict; context=nothing)

Receive a schema in string format or in a text file, return an object of type schema
"""
function Schema(_schema::String, resolvers::Dict; context=nothing)
if '.' in _schema
  _schema = open(_schema) do file
      read(file, String)
    end
end

symbol_extract =getfield_types()
vi= Visitante(Parse(_schema))
vi.visitante(symbol_extract)
symbol_table = symbol_extract.simbolos

return Schema(symbol_table, resolvers, context=context)

end

"""
    Schema(_schema::Dict, resolvers::Dict; context=nothing)
Receive a schema in dictionary format, return an object of type schema
"""
function Schema(_schema::Dict, resolvers::Dict; context=nothing)

symbol_table = _schema

    function execute(query::String; operationName=nothing, Variables=nothing, initialValue=nothing)
      #si la solicitud no esta validada, validarla
      document = Parse(query)

      count_operations = length(document.definitions)

      if (count_operations > 1) && (operationName==nothing)
        throw(GraphQLError("{\"data\": null,\"errors\": [{\"message\": \"No operation named.\"}]}"))
      end

      Validatequery(document)

       operation= nothing
       type_operation = " "

       if operationName==nothing
          operation= document
          type_operation= document.definitions[1].operation
      else
          data = GetOperation(document,operationName)
          if !haskey(data.found, "extracted_operation")
              throw(GraphQLError("{\"data\": null,\"errors\": [{\"message\": \"$(operationName) operation not found.\"}]}"))
          else
            operation = data.found["extracted_operation"]
            type_operation = data.found["operation_type"]
          end
      end

       #pero si esta misma solicitud ya se valido antes, pues solo recuperarla de cache

      if type_operation =="query"
        return JSON.json(ExecuteQuery(operation, symbol_table,resolvers, context , Variables=Variables, initialValue=nothing))
      elseif type_operation == "mutation"
        return JSON.json(ExecuteMutation(operation, symbol_table,resolvers, context , Variables=Variables, initialValue=nothing))
      #elseif type_operation == "subscribe"
       # return JSON.json(Subscribe(operation, symbol_table,resolvers, context , Variables=nothing, initialValue=nothing))
      end

      return JSON.json("{}")#
    end

 return schema(execute)

end


text:
@testset "peak finding - $P" for P in [PeakMesh()]
    data = randn(100, 100)
    idxs = [1, 700, 1524]
    fake_peaks = randn(length(idxs)) .+ 10
    data[idxs] .= fake_peaks

    table = extract_sources(P, data)
    @test table.value[1:3] == sort(fake_peaks, rev = true)
end

@testset "Peak Mesh" begin
    @test PeakMesh(box_size = 3) == PeakMesh(box_size = (3, 3))
end

@testset "interface - $P" for P in [PeakMesh()]
    data = randn(100, 100)
    idxs = [1, 700, 1524]
    fake_peaks = randn(length(idxs)) .+ 10
    data[idxs] .= fake_peaks

    table = extract_sources(P, data)
    table2 = extract_sources(P, data, zeros(100, 100))
    @test table == table2
end


text:
using MuladdMacro

export tai_offset

include(joinpath("constants", "tdb.jl"))

const OFFSET_TAI_TT = 32.184
const LG_RATE = 6.969290134e-10
const LB_RATE = 1.550519768e-8

"""
    tai_offset(ep)

Returns the offset from TAI for the epoch `ep`.
"""
tai_offset(ep::Epoch) = ep.ts_offset

tai_offset(::InternationalAtomicTime, ep) = 0.0

"""
    tai_offset(TT, ep)

Returns the difference TT-TAI in seconds at the epoch `ep`.
"""
tai_offset(::TerrestrialTime, ep) = OFFSET_TAI_TT

"""
    tai_offset(TCG, ep)

Returns the difference TCG-TAI in seconds at the epoch `ep`.
"""
tai_offset(::GeocentricCoordinateTime, ep) = tai_offset(TT, ep) + LG_RATE * value(ep - EPOCH_77)

"""
    tai_offset(TCB, ep)

Returns the difference TCB-TAI in seconds at the epoch `ep`.
"""
tai_offset(::BarycentricCoordinateTime, ep) = tai_offset(TDB, ep) + LB_RATE * value(ep - EPOCH_77)

"""
    tai_offset(UTC, ep)

Returns the difference UTC-TAI in seconds at the epoch `ep`.
"""
@inline function tai_offset(::CoordinatedUniversalTime, ep)
    offset = findoffset(ep)
    offset === nothing && return 0.0

    -getoffset(offset, ep)
end

"""
    tai_offset(UT1, ep)

Returns the difference UT1-TAI in seconds at the epoch `ep`.
"""
@inline function tai_offset(::UniversalTime, ep)
    jd = value(julian(UTC, ep))
    tai_offset(UTC, ep) + getΔUT1(jd)
end

"""
    tai_offset(TDB, ep)

Returns the difference TDB-TAI in seconds at the epoch `ep`.

This routine is accurate to ~40 microseconds in the interval 1900-2100.

!!! note
    An accurate transformation between TDB and TT depends on the
    trajectory of the observer. For two observers fixed on Earth's surface
    the quantity TDB-TT can differ by as much as ~4 microseconds. See
    [`tai_offset(TDB, ep, elong, u, v)`](@ref).

### References ###

- [https://www.cv.nrao.edu/~rfisher/Ephemerides/times.html#TDB](https://www.cv.nrao.edu/~rfisher/Ephemerides/times.html#TDB)
- [Issue #26](https://github.com/JuliaAstro/AstroTime.jl/issues/26)

"""
@inline function tai_offset(::BarycentricDynamicalTime, ep)
    dt = value(j2000(TT, ep))
    g = deg2rad(357.53 + 0.9856003dt)
    tai_offset(TT, ep) + 0.001658sin(g) + 0.000014sin(2g)
end

"""
    tai_offset(TDB, ep, elong, u, v)

Returns the difference TDB-TAI in seconds at the epoch `ep` for an observer on Earth.

### Arguments ###

- `ep`: Current epoch
- `elong`: Longitude (east positive, radians)
- `u`: Distance from Earth's spin axis (km)
- `v`: Distance north of equatorial plane (km)

### References ###

- [ERFA](https://github.com/liberfa/erfa/blob/master/src/dtdb.c)
"""
function tai_offset(::BarycentricDynamicalTime, ep, elong, u, v)
    ut = fractionofday(UT1Epoch(ep))
    t = value(centuries(j2000(TT, ep))) / 10.0
    # Convert UT to local solar time in radians.
    tsol = mod(ut, 1.0) * 2π  + elong

    # FUNDAMENTAL ARGUMENTS:  Simon et al. 1994.
    # Combine time argument (millennia) with deg/arcsec factor.
    w = t / 3600.0
    # Sun Mean Longitude.
    elsun = deg2rad(mod(280.46645683 + 1296027711.03429 * w, 360.0))
    # Sun Mean Anomaly.
    emsun = deg2rad(mod(357.52910918 + 1295965810.481 * w, 360.0))
    # Mean Elongation of Moon from Sun.
    d = deg2rad(mod(297.85019547 + 16029616012.090 * w, 360.0))
    # Mean Longitude of Jupiter.
    elj = deg2rad(mod(34.35151874 + 109306899.89453 * w, 360.0))
    # Mean Longitude of Saturn.
    els = deg2rad(mod(50.07744430 + 44046398.47038 * w, 360.0))
    # TOPOCENTRIC TERMS:  Moyer 1981 and Murray 1983.
    wt = 0.00029e-10 * u * sin(tsol + elsun - els) +
        0.00100e-10 * u * sin(tsol - 2.0 * emsun) +
        0.00133e-10 * u * sin(tsol - d) +
        0.00133e-10 * u * sin(tsol + elsun - elj) -
        0.00229e-10 * u * sin(tsol + 2.0 * elsun + emsun) -
        0.02200e-10 * v * cos(elsun + emsun) +
        0.05312e-10 * u * sin(tsol - emsun) -
        0.13677e-10 * u * sin(tsol + 2.0 * elsun) -
        1.31840e-10 * v * cos(elsun) +
        3.17679e-10 * u * sin(tsol)

    # =====================
    # Fairhead et al. model
    # =====================

    # T**0
    w0 = 0.0
    for j in eachindex(fairhd0)
        @muladd w0 += fairhd0[j][1] * sin(fairhd0[j][2] * t + fairhd0[j][3])
    end
    # T**1
    w1 = 0.0
    for j in eachindex(fairhd1)
        @muladd w1 += fairhd1[j][1] * sin(fairhd1[j][2] * t + fairhd1[j][3])
    end
    # T**2
    w2 = 0.0
    for j in eachindex(fairhd2)
        @muladd w2 += fairhd2[j][1] * sin(fairhd2[j][2] * t + fairhd2[j][3])
    end
    # T**3
    w3 = 0.0
    for j in eachindex(fairhd3)
        @muladd w3 += fairhd3[j][1] * sin(fairhd3[j][2] * t + fairhd3[j][3])
    end
    # T**4
    w4 = 0.0
    for j in eachindex(fairhd4)
        @muladd w4 += fairhd4[j][1] * sin(fairhd4[j][2] * t + fairhd4[j][3])
    end

    # Multiply by powers of T and combine.
    wf = @evalpoly t w0 w1 w2 w3 w4

    # Adjustments to use JPL planetary masses instead of IAU.
    wj = 0.00065e-6 * sin(6069.776754 * t + 4.021194) +
        0.00033e-6 * sin(213.299095 * t + 5.543132) +
        (-0.00196e-6 * sin(6208.294251 * t + 5.696701)) +
        (-0.00173e-6 * sin(74.781599 * t + 2.435900)) +
        0.03638e-6 * t * t

    # TDB-TT in seconds.
    w = wt + wf + wj

    tai_offset(TT, ep) + w
end

tai_offset(::InternationalAtomicTime, date::Date, time::Time) = 0.0

@inline function tai_offset(::CoordinatedUniversalTime, date::Date, time::Time)
    minute_in_day = hour(time) * 60 + minute(time)
    correction = minute_in_day < 0 ? (minute_in_day - 1439) ÷ 1440 : minute_in_day ÷ 1440
    offset = findoffset(julian(date) + correction)
    offset === nothing && return 0.0

    getoffset(offset, date, time)
end

@inline function tai_offset(scale, date::Date, time::Time, args...)
    ref = Epoch{TAI}(date, time)
    offset = 0.0
    # TODO: Maybe replace this with a simple convergence check
    for _ in 1:8
        offset = -tai_offset(scale, Epoch{TAI}(ref, offset), args...)
    end
    offset
end


text:
module Jockey
# Repl
include("JockRepl.jl")

export parse_bash_command
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct Logger <: SwaggerModel
    log_fifo::Union{ Nothing, String } # log_fifo
    metrics_fifo::Union{ Nothing, String } # metrics_fifo
    level::Union{ Nothing, String } # level
    show_level::Union{ Nothing, Bool } # show_level
    show_log_origin::Union{ Nothing, Bool } # show_log_origin
    options::Union{ Nothing, Vector{String} } # options

    function Logger(;log_fifo=nothing, metrics_fifo=nothing, level="Warning", show_level=false, show_log_origin=false, options=nothing)
        o = new()
        set_field!(o, :log_fifo, log_fifo)
        set_field!(o, :metrics_fifo, metrics_fifo)
        set_field!(o, :level, level)
        set_field!(o, :show_level, show_level)
        set_field!(o, :show_log_origin, show_log_origin)
        set_field!(o, :options, options)
        o
    end
end # type Logger

const _name_map_Logger = Dict{String,Symbol}(["log_fifo"=>:log_fifo, "metrics_fifo"=>:metrics_fifo, "level"=>:level, "show_level"=>:show_level, "show_log_origin"=>:show_log_origin, "options"=>:options])
const _field_map_Logger = Dict{Symbol,String}([:log_fifo=>"log_fifo", :metrics_fifo=>"metrics_fifo", :level=>"level", :show_level=>"show_level", :show_log_origin=>"show_log_origin", :options=>"options"])
Swagger.name_map(::Type{ Logger }) = _name_map_Logger
Swagger.field_map(::Type{ Logger }) = _field_map_Logger

const _allowed_Logger_level = ["Error", "Warning", "Info", "Debug"]

function check_required(o::Logger)
    (o.log_fifo === nothing) && (return false)
    (o.metrics_fifo === nothing) && (return false)
    true
end

function validate_field(o::Logger, name::Symbol, val)
    if name === :level
        Swagger.validate_param(name, "Logger", :enum, val, _allowed_Logger_level)
    end
end


text:
using .SDF
using Test
file_name = "0002.sdf"
bloks = fetch_blocks(file_name)
f = open(file_name)
ar1=read!(f, bloks[4])
ar4, idx4=Main.SDF.read2(f, bloks[4]; req_pts=((1, 3), (2, 6), (3, 6)), fn=x->x>0)
close(f)

@test ar4 == ar1[idx4]


text:
using DataStructures
using ArgParse

export create_output_parser, output_params_dict, process_output_args

function create_output_parser()
    s = ArgParseSettings()

    @add_arg_table! s begin
        "--output_method"
            help = "Method for selecting amplitudes to output. (uniform, rejection, list)"
            default = :List
            arg_type = Symbol
        "--num_outputs", "-n"
            help = "Number of amplitudes or bitstring samples to output"
            default = nothing
        "--M"
            help = "Constant to use for rejection sampling"
            default = 0.001
            arg_type = Float64
        "--fix_M"
            help = "Fix rejection sampling constant for frugal sampling"
            default = false
            arg_type = Bool
        "--bitstrings"
            help = "The bitstrings to compute amplitudes for if list output method is selected"
            default = nothing
        "--output_seed"
            help = "Seed to use for sampling output bitstrings"
            default = nothing
    end

    return s
end

"""
function output_params_dict(qubits::Int,
                            num_outputs::Int64=10;
                            output_method::Symbol=:List,
                            seed::Union{Int64, Nothing}=nothing,
                            M::Float64=0.0001,
                            fix_M::Bool=false,
                            bitstrings::Union{Vector{String}, Nothing}=nothing)

Function to construct dictionary with appropriate paramters to describe sampling approach.
"""
function output_params_dict(num_qubits::Int,
                            num_outputs::Int=10;
                            output_method::Symbol=:List,
                            seed::Union{Int, Nothing}=nothing,
                            M::Float64=0.0001,
                            fix_M::Bool=false,
                            bitstrings::Union{Vector{String}, Nothing}=nothing)
    output_args = OrderedDict()
    output_args[:method] = output_method
    output_params = OrderedDict()
    if output_method == :Rejection
        output_params[:num_qubits] = num_qubits
        output_params[:M] = M
        output_params[:fix_M] = fix_M
        output_params[:seed] = seed
        output_params[:num_samples] = num_outputs
    elseif output_method == :List
        if bitstrings === nothing
            bitstrings = collect(amplitudes_uniform(num_qubits, seed, num_outputs))
        else num_outputs = length(bitstrings) end
        output_params[:num_samples] = num_outputs
        output_params[:bitstrings] = bitstrings
    elseif output_method == :Uniform
        output_params[:num_qubits] = num_qubits
        output_params[:num_samples] = num_outputs
        output_params[:seed] = seed
    else
        @error("Output method \"$(output_method)\" not supported")
    end
    output_args[:params] = output_params
    output_args
end

"""
function parse_output_args(qubits, parsed_args)

Process parsed output arguments and construct output parameters dictionary
"""
function process_output_args(num_qubits, parsed_args)
    # Output parameters.
    output_method = parsed_args["output_method"]
    num_outputs = parsed_args["num_outputs"]
    if num_outputs === nothing
        num_outputs = 10
    else num_outputs = parse(Int64, num_outputs) end
    M = parsed_args["M"]
    fix_M = parsed_args["fix_M"]
    bitstrings = parsed_args["bitstrings"]
    if bitstrings !== nothing
        if match(r"[01|,]*", bitstrings) === nothing
            @error("Bistrings must only contains '0','1',','")
        end
        bitstrings = split(bitstrings, ",")
    end
    seed = parsed_args["output_seed"]
    seed === nothing || (seed = parse(Int64, seed))

    output_params_dict(num_qubits,
                       num_outputs;
                       output_method=output_method,
                       seed=seed,
                       M=M,
                       fix_M=fix_M,
                       bitstrings=bitstrings)
end


text:
using MechanicalSketch
import MechanicalSketch: foil_draw, °, background, sethue, O, finish
import MechanicalSketch: m, N, kN, s, arrow, color_from_palette, color_with_lumin
import MechanicalSketch: empty_figure, PALETTE

let
BACKCOLOR = color_with_lumin(PALETTE[5], 30)
function restart()
    empty_figure(filename = joinpath(@__DIR__, "test_7.png"))
    background(BACKCOLOR)
    sethue(PALETTE[5])
end
restart()
p = O + (-9m, 9m)
foil_draw(p)
p += (0m, -1m)
foil_draw(p, rel_scale = 2)
p += (0m, -1m)
foil_draw(p, rel_scale = 2, backgroundcolor = BACKCOLOR)
p += (0m, -1m)
foil_draw(p, rel_scale = 4, backgroundcolor = BACKCOLOR)
p += (0m, -1m)
sethue(PALETTE[10])
foil_draw(p, rel_scale = 8, backgroundcolor = BACKCOLOR,
          α = -6°)

sethue(PALETTE[9])

p += (0m, -2m)
sethue(PALETTE[10])
foil_draw(p, rel_scale = 8, backgroundcolor = BACKCOLOR,
          α = -10°)
# Force vector
sethue(color_from_palette("green"))
arrow(p, 1kN, 5kN, α = -10°, backgroundcolor = BACKCOLOR)

# Force vector
p += (0m, -1m)
sethue(PALETTE[8])
arrow(p, 1kN, 5kN, α = 45°, backgroundcolor = BACKCOLOR, labellength = true)

p += (0m, -1m)
sethue(PALETTE[8])
arrow(p, 10kN, 0kN, α = 0°, backgroundcolor = BACKCOLOR)

# Velocity vector
p += (8m, -1m)
sethue(PALETTE[6])
arrow(p, 7m/s, 0m/s, α = 0°)

p += (0m, -1m)
sethue(PALETTE[3])
arrow(p, 30m/s, 3m/s, α = 0°)

p += (0m, -1m)
sethue(PALETTE[2])
arrow(p, 10m/s, 0m/s, α = 0°)

finish()

nothing
end


text:
function Base.show(io::IO, gd::GroupedDataTable)
    N = length(gd)
    println(io, "$(typeof(gd))  $N groups with keys: $(gd.cols)")
    if N > 0
        println(io, "First Group:")
        show(io, gd[1])
    end
    if N > 1
        print(io, "\n⋮\n")
        println(io, "Last Group:")
        show(io, gd[N])
    end
end

function Base.showall(io::IO, gd::GroupedDataTable)
    N = length(gd)
    println(io, "$(typeof(gd))  $N groups with keys: $(gd.cols)")
    for i = 1:N
        println(io, "gd[$i]:")
        show(io, gd[i])
    end
end


text: check(arr, element) = element in arr

max_stars_repo_name: UlrichBerntien/Codewars-Katas

max_issues_repo_name: UlrichBerntien/Codewars-Katas

max_forks_repo_name: UlrichBerntien/Codewars-Katas


text:
using Grid

function interp_3d(data::Array{Float64, 2}, num_points::Int)
    # interpolates with num_points per original point
    interp_type = InterpQuadratic
    y1 = InterpGrid(data[:,1], BCnil, interp_type)
    y2 = InterpGrid(data[:,2], BCnil, interp_type)
    y3 = InterpGrid(data[:,3], BCnil, interp_type)
    output = zeros((size(data, 1)-1)*num_points + 1, 3)
    for i in 1:(size(data, 1)-1)
        index = 1
        for j in range(0, 1/num_points, num_points)
            output[(i-1)*num_points + index, :] = [y1[i+j], y2[i+j], y3[i+j]]
            index += 1
        end
    end
    output[end, :] = data[end, :]
    return output
end

function centroid(data::Array{Float64, 2})
    # Returns the centroid of the points - a 3x1 vector.
    return mean(data, 1)
end

function center_data(data::Array{Float64, 2})
    # centers the data such that the centroid is at 0.
    centroid = mean(data, 1)
    return data .- centroid
end


text:
@testset "Element constructors" begin

    g1 = MiniOPF.Generator("1", 0.1)
    g2 = MiniOPF.Generator("2", 0.2)
    g3 = MiniOPF.Generator("3", 0.3)
    println(g1)

    l1 = MiniOPF.Line("a", ("1", "2"), 1.0)
    l2 = MiniOPF.Line("b", ("2", "3"), 1.0)
    println(l1)

    bus_ids = ["1", "2"]
    bus_ids_e = ["1", "2", "3"]
    bus_ids_e2 = ["1", "1", "2"]

    branch_ids = ["a"]
    branch_ids_e = ["a", "b"]
    branch_ids_e2 = ["a", "b", "b"]

    generators = [g1, g2]
    generators_e = [g1, g2, g3]

    branches = [l1]
    branches_e = [l1, l2]
    @testset "Generators" begin
        gen_fields = [:bus, :id, :gtype, :price, :startup, :shutdown, :ramp_up, :ramp_down, :upper_limit, :lower_limit]
        @test isempty(symdiff(fieldnames(g1), gen_fields))
    end
    @testset "Branches" begin
        lin_fields = [:branch_id, :from_to_bus, :thermal_limit]
        @test isempty(symdiff(fieldnames(l1), lin_fields))
    end

    @testset "Grid" begin
        g = MiniOPF.Grid(bus_ids, branch_ids, generators, branches)
        println(g)
        grid_fields = [:bus_ids, :branch_ids, :generators, :branches, :incidence]
        @test isempty(symdiff(fieldnames(g), grid_fields))

        @test try MiniOPF.Grid(bus_ids_e, branch_ids, generators, branches) catch true end
        @test try MiniOPF.Grid(bus_ids, branch_ids_e, generators, branches) catch true end
        @test try MiniOPF.Grid(bus_ids, branch_ids, generators_e, branches) catch true end
        @test try MiniOPF.Grid(bus_ids, branch_ids, generators, branches_e) catch true end
        @test try MiniOPF.Grid(bus_ids_e2, branch_ids, generators, branches_e) catch true end
        @test try MiniOPF.Grid(bus_ids, branch_ids_e2, generators, branches_e) catch true end
    end

    @testset "Load" begin
        load = MiniOPF.Load(bus_ids, [1, 1])
        println(load)
        @test isempty(symdiff(fieldnames(load), [:bus_ids, :nodal_load]))
    end

end


text:
__precompile__(true)

module MinMaxFilter

# This is a port of the Lemire min max filter as implemented by Bruno Luong
# http://arxiv.org/abs/cs.DS/0610046
# http://lemire.me/
# http://www.mathworks.com/matlabcentral/fileexchange/24705-min-max-filter

export minmax_filter

using Base.Cartesian

type Wedge{A <: AbstractArray}
    buffer::A
    size::Int
    n::Int
    first::Int
    last::Int
    mxn::Int
end

for N = 2:4
    @eval begin
    function minmax_filter{T <: Number}(A::Array{T, $N}, window::Array{Int, 1})

        maxval_temp = copy(A); minval_temp = copy(A)

        for dim = 1:$N

            # For all but the last dimension
            @nloops $(N-1) i maxval_temp begin

                # Create index for full array (fa) length
                @nexprs $(N)   j->(fa_{j} = 1:size(maxval_temp)[j])
                @nexprs $(N-1) j->(fa_{j} = i_j)

                # Create index for short array (sa) length
                @nexprs $(N)   j->(sa_{j} = 1:size(maxval_temp)[j] - window[dim] + 1)
                @nexprs $(N-1) j->(sa_{j} = i_j)

                # Filter the last dimension
                (@nref $N minval_temp sa) = min_filter(vec( @nref $N minval_temp fa), window[dim])
                (@nref $N maxval_temp sa) = max_filter(vec( @nref $N maxval_temp fa), window[dim])

            end

            # Circular shift the dimensions
            maxval_temp = permutedims(maxval_temp, mod(collect(1:$N), $N)+1)
            minval_temp = permutedims(minval_temp, mod(collect(1:$N), $N)+1)

        end

        # The dimensions to extract
        @nexprs $N j->(a_{j} = 1:size(A, j)-window[j]+1)

        # Extract set dimensions
        maxval_out = @nref $N maxval_temp a
        minval_out = @nref $N minval_temp a

        return minval_out, maxval_out
    end
    end
end

function minmax_filter{T <: Number}(a::AbstractArray{T}, window::Int)

    n = length(a)

    # Initialise the output variables
    # This is the running minimum and maximum over the specified window length
    minval = zeros(T, 1, n-window+1)
    maxval = zeros(T, 1, n-window+1)

    # Initialise the internal wedges
    # U[1], L[1] are the location of the global maximum and minimum
    # U[2], L[2] are the maximum and minimum over (U1, inf)
    L = Wedge(zeros(Int,1,window+1), window+1, 0, 1, 0, 0)          # Min
    U = Wedge(zeros(Int,1,window+1), window+1, 0, 1, 0, 0)

    for i = 2:n
        if i > window
            if !wedgeisempty(U)
                maxval[i-window] = a[getfirst(U)]
            else
                maxval[i-window] = a[i-1]
            end
            if !wedgeisempty(L)
                minval[i-window] = a[getfirst(L)]
            else
                minval[i-window] = a[i-1]
            end
        end # window

        if a[i] > a[i-1]
            pushback!(L, i-1)
            if i==window+getfirst(L); L=popfront(L); end
            while !wedgeisempty(U)
                if a[i] <= a[getlast(U)]
                    if i == window+getfirst(U); U = popfront(U); end
                    break
                end
                U = popback(U)
            end

        else

            pushback!(U, i-1)
            if i==window+getfirst(U); U=popfront(U); end

            while !wedgeisempty(L)
                if a[i] >= a[getlast(L)]
                    if i == window+getfirst(L); L = popfront(L); end
                    break
                end
                L = popback(L)
            end

        end  # a>a-1

    end # for i

    i = n+1
    if !wedgeisempty(U)
        maxval[i-window] = a[getfirst(U)]
    else
        maxval[i-window] = a[i-1]
    end

    if !wedgeisempty(L)
        minval[i-window] = a[getfirst(L)]
    else
        minval[i-window] = a[i-1]
    end

    return minval, maxval
end

function min_filter(a::AbstractArray, window::Int)

    minval, maxval = minmax_filter(a, window)

    return minval
end

function max_filter(a::AbstractArray, window::Int)

    minval, maxval = minmax_filter(a, window)

    return maxval
end

function wedgeisempty(X::Wedge)
    X.n <= 0
end

function pushback!(X::Wedge, v)
    X.last += 1
    if X.last > X.size
        X.last = 1
    end
    X.buffer[X.last] = v
    X.n = X.n+1
    X.mxn = max(X.mxn, X.n)
end

function getfirst(X::Wedge)
    X.buffer[X.first]
end

function getlast(X::Wedge)
    X.buffer[X.last]
end

function popfront(X::Wedge)
    X.n = X.n-1
    X.first = mod(X.first, X.size) + 1
    return X
end

function popback(X::Wedge)
    X.n = X.n-1
    X.last = mod(X.last-2, X.size) + 1
    return X
end

end # module


text:
promote_rule(::Type{FastRational{T,IsReduced}}, ::Type{T}) where {T<:BitInteger} = FastRational{T,IsReduced}
promote_rule(::Type{FastRational{T,MayReduce}}, ::Type{T}) where {T<:BitInteger} = FastRational{T,IsReduced}
promote_rule(::Type{FastRational{T,IsReduced}}, ::Type{Rational{T}}) where {T<:BitInteger} = FastRational{T,IsReduced}
promote_rule(::Type{FastRational{T,MayReduce}}, ::Type{Rational{T}}) where {T<:BitInteger} = FastRational{T,IsReduced}

promote_rule(::Type{FastRational{T,IsReduced}}, ::Type{A}) where {T,A} = FastRational{T,IsReduced}
promote_rule(::Type{FastRational{T,MayReduce}}, ::Type{A}) where {T,A} = FastRational{T,IsReduced}

convert(::Type{FastRational{T,IsReduced}}, x::Rational{T}) where {T} = FastRational{T,IsReduced}(x.num, x.den)
convert(::Type{FastRational{T,MayReduce}}, x::Rational{T}) where {T} = FastRational{T,IsReduced}(x.num, x.den)
convert(::Type{Rational{T}}, x::FastRational{T,MayReduce}) where {T} = Rational{T}(canonical(x.num, x.den))
convert(::Type{Rational{T}}, x::FastRational{T,IsReduced}) where {T} = Rational{T}(x.num, x.den)

convert(::Type{FastRational{T,IsReduced}}, x::T) where {T} = FastRational{T,IsReduced}(x, one(T))
convert(::Type{FastRational{T,MayReduce}}, x::T) where {T} = FastRational{T,IsReduced}(x, one(T))


text:
export MNISTData, featureSize, numTrain, numTest, numClasses

immutable MNISTData{A}
    trainImages::A
    testImages::A
    trainLabels::A
    testLabels::A
end

featureSize(data::MNISTData) = dims(data.trainImages, 1)

numClasses(data::MNISTData) = dims(data.trainLabels, 1)

numTrain(data::MNISTData) = dims(data.trainImages, 0)

numTest(data::MNISTData) = dims(data.testImages, 0)

max_stars_repo_name: unbornchikken/julia-ml-proto

max_issues_repo_name: unbornchikken/julia-ml-proto

max_forks_repo_name: unbornchikken/julia-ml-proto


text:
################################################################################
# Runs the test suite in benchmark mode and saves the results to a JSON file
################################################################################
using NonlinearEigenproblemsTest
using Logging

# turn off logging of @info statements and test output
Base.CoreLogging.disable_logging(Logging.Info)
set_displaylevel(0)

include("benchmark_utils.jl")
include(normpath("..", "run_all_tests.jl"))

if length(ARGS) < 1
    println("Benchmark JSON file name required:\n\n$(basename(@__FILE__)) benchmark_file [duration_seconds] [test_name_regex]")
else
    enable_benchmark()
    length(ARGS) >= 2 && set_benchmark_duration_seconds(parse(Float64, ARGS[2]))
    test_name_regex = length(ARGS) < 3 ? "" : ARGS[3]
    test_results = @timed run_all_tests(test_name_regex)
    save_benchmark(test_results[1:2]..., ARGS[1])
    print_benchmark(ARGS[1])
end


text:
colsupport(::TriangularLayout{'L'}, A, j) = colsupport(triangulardata(A), j) ∩ (minimum(j):size(A,1))
colsupport(::TriangularLayout{'U'}, A, j) = colsupport(triangulardata(A), j) ∩ OneTo(maximum(j))
rowsupport(::TriangularLayout{'U'}, A, j) = rowsupport(triangulardata(A), j) ∩ (minimum(j):size(A,2))
rowsupport(::TriangularLayout{'L'}, A, j) = rowsupport(triangulardata(A), j) ∩ OneTo(maximum(j))

###
# Lmul
###

@inline function materialize!(M::BlasMatLmulVec{<:TriangularLayout{UPLO,UNIT,<:AbstractColumnMajor},
                                         <:AbstractStridedLayout}) where {UPLO,UNIT}
    A,x = M.A,M.B
    BLAS.trmv!(UPLO, 'N', UNIT, triangulardata(A), x)
end

@inline function materialize!(M::BlasMatLmulVec{<:TriangularLayout{'U',UNIT,<:AbstractRowMajor},
                                   <:AbstractStridedLayout}) where UNIT
    A,x = M.A,M.B
    BLAS.trmv!('L', 'T', UNIT, transpose(triangulardata(A)), x)
end

@inline function materialize!(M::BlasMatLmulVec{<:TriangularLayout{'L',UNIT,<:AbstractRowMajor},
                                   <:AbstractStridedLayout}) where UNIT
    A,x = M.A,M.B
    BLAS.trmv!('U', 'T', UNIT, transpose(triangulardata(A)), x)
end

@inline function materialize!(M::BlasMatLmulVec{<:TriangularLayout{'U',UNIT,<:ConjLayout{<:AbstractRowMajor}},
                                   <:AbstractStridedLayout,<:BlasComplex}) where UNIT
    A,x = M.A,M.B
    BLAS.trmv!('L', 'C', UNIT, triangulardata(A)', x)
end

@inline function materialize!(M::BlasMatLmulVec{<:TriangularLayout{'L',UNIT,<:ConjLayout{<:AbstractRowMajor}},
                                   <:AbstractStridedLayout,<:BlasComplex}) where UNIT
    A,x = M.A,M.B
    BLAS.trmv!('U', 'C', UNIT, triangulardata(A)', x)
end
# Triangular * Matrix

@inline function materialize!(M::BlasMatLmulMat{<:TriangularLayout{UPLO,UNIT,<:AbstractColumnMajor},
                                         <:AbstractStridedLayout, T}) where {UPLO,UNIT,T<:BlasFloat}
    A,x = M.A,M.B
    BLAS.trmm!('L', UPLO, 'N', UNIT, one(T), triangulardata(A), x)
end

@inline function materialize!(M::BlasMatLmulMat{<:TriangularLayout{'L',UNIT,<:AbstractRowMajor},
                                   <:AbstractStridedLayout, T}) where {UNIT,T<:BlasFloat}
    A,x = M.A,M.B
    BLAS.trmm!('L', 'U', 'T', UNIT, one(T), transpose(triangulardata(A)), x)
end

@inline function materialize!(M::BlasMatLmulMat{<:TriangularLayout{'U',UNIT,<:AbstractRowMajor},
    <:AbstractStridedLayout, T}) where {UNIT,T<:BlasFloat}
A,x = M.A,M.B
BLAS.trmm!('L', 'L', 'T', UNIT, one(T), transpose(triangulardata(A)), x)
end

@inline function materialize!(M::BlasMatLmulMat{<:TriangularLayout{'L',UNIT,<:ConjLayout{<:AbstractRowMajor}},
                                   <:AbstractStridedLayout, T}) where {UNIT,T<:BlasComplex}
    A,x = M.A,M.B
    BLAS.trmm!('L', 'U', 'C', UNIT, one(T), triangulardata(A)', x)
end

@inline function materialize!(M::BlasMatLmulMat{<:TriangularLayout{'U',UNIT,<:ConjLayout{<:AbstractRowMajor}},
                                                <:AbstractStridedLayout, T}) where {UNIT,T<:BlasComplex}
A,x = M.A,M.B
BLAS.trmm!('L', 'L', 'C', UNIT, one(T), triangulardata(A)', x)
end

materialize!(M::MatLmulMat{<:TriangularLayout}) = lmul!(M.A, M.B)

###
# Rmul
###

@inline function materialize!(M::BlasMatRmulMat{<:AbstractStridedLayout,
                                                <:TriangularLayout{UPLO,UNIT,<:AbstractColumnMajor},T}) where {UPLO,UNIT,T<:BlasFloat}
    x,A = M.A,M.B
    BLAS.trmm!('R', UPLO, 'N', UNIT, one(T), triangulardata(A), x)
end

@inline function materialize!(M::BlasMatRmulMat{<:AbstractStridedLayout,
                                                <:TriangularLayout{'L',UNIT,<:AbstractRowMajor},T}) where {UNIT,T<:BlasFloat}
    x,A = M.A,M.B
    BLAS.trmm!('R', 'U', 'T', UNIT, one(T), transpose(triangulardata(A)), x)
end

@inline function materialize!(M::BlasMatRmulMat{<:AbstractStridedLayout,
                                                <:TriangularLayout{'U',UNIT,<:AbstractRowMajor},T}) where {UNIT,T<:BlasFloat}
x,A = M.A,M.B
BLAS.trmm!('R', 'L', 'T', UNIT, one(T), transpose(triangulardata(A)), x)
end

@inline function materialize!(M::BlasMatRmulMat{<:AbstractStridedLayout,
                                                <:TriangularLayout{'L',UNIT,<:ConjLayout{<:AbstractRowMajor}},T}) where {UPLO,UNIT,T<:BlasComplex}
    x,A = M.A,M.B
    BLAS.trmm!('R', 'U', 'C', UNIT, one(T), triangulardata(A)', x)
end

@inline function materialize!(M::BlasMatRmulMat{<:AbstractStridedLayout,
                                                <:TriangularLayout{'U',UNIT,<:ConjLayout{<:AbstractRowMajor}},T}) where {UPLO,UNIT,T<:BlasComplex}
x,A = M.A,M.B
BLAS.trmm!('R', 'L', 'C', UNIT, one(T), triangulardata(A)', x)
end

materialize!(M::MatRmulMat{<:AbstractStridedLayout,<:TriangularLayout}) = rmul!(M.A, M.B)

########
# Ldiv
########

@inline function copyto!(dest::AbstractArray, M::Ldiv{<:TriangularLayout})
    A, B = M.A, M.B
    dest ≡ B || (dest .= B)
    materialize!(Ldiv(A, dest))
end

for UNIT in ('U', 'N')
    for UPLO in ('L', 'U')
        @eval @inline materialize!(M::BlasMatLdivVec{<:TriangularLayout{$UPLO,$UNIT,<:AbstractColumnMajor},
                                            <:AbstractStridedLayout}) =
            BLAS.trsv!($UPLO, 'N', $UNIT, triangulardata(M.A), M.B)
    end

    @eval begin
        @inline materialize!(M::BlasMatLdivVec{<:TriangularLayout{'U',$UNIT,<:AbstractRowMajor},
                                                        <:AbstractStridedLayout}) =
            BLAS.trsv!('L', 'T', $UNIT, transpose(triangulardata(M.A)), M.B)

        @inline materialize!(M::BlasMatLdivVec{<:TriangularLayout{'L',$UNIT,<:AbstractRowMajor},
                                                        <:AbstractStridedLayout}) =
            BLAS.trsv!('U', 'T', $UNIT, transpose(triangulardata(M.A)), M.B)

        @inline materialize!(M::BlasMatLdivVec{<:TriangularLayout{'U',$UNIT,<:ConjLayout{<:AbstractRowMajor}},
                                                        <:AbstractStridedLayout}) =
            BLAS.trsv!('L', 'C', $UNIT, triangulardata(M.A)', M.B)

        @inline materialize!(M::BlasMatLdivVec{<:TriangularLayout{'L',$UNIT,<:ConjLayout{<:AbstractRowMajor}},
                                                        <:AbstractStridedLayout}) =
            BLAS.trsv!('U', 'C', $UNIT, triangulardata(M.A)', M.B)
    end
end

function materialize!(M::MatLdivMat{<:TriangularLayout})
    A,X = M.A,M.B
    size(A,2) == size(X,1) || thow(DimensionMismatch("Dimensions must match"))
    @views for j in axes(X,2)
        materialize!(Ldiv(A, X[:,j]))
    end
    X
end

function materialize!(M::MatLdivVec{<:TriangularLayout{'U','N'}})
    A,b = M.A,M.B
    require_one_based_indexing(A, b)
    n = size(A, 2)
    if !(n == length(b))
        throw(DimensionMismatch("second dimension of left hand side A, $n, and length of right hand side b, $(length(b)), must be equal"))
    end
    data = triangulardata(A)
    @inbounds for j in reverse(colsupport(b,1))
        iszero(data[j,j]) && throw(SingularException(j))
        bj = b[j] = data[j,j] \ b[j]
        for i in (1:j-1) ∩ colsupport(data,j)
            b[i] -= data[i,j] * bj
        end
    end
    b
end

function materialize!(M::MatLdivVec{<:TriangularLayout{'U','U'}})
    A,b = M.A,M.B
    require_one_based_indexing(A, b)
    n = size(A, 2)
    if !(n == length(b))
        throw(DimensionMismatch("second dimension of left hand side A, $n, and length of right hand side b, $(length(b)), must be equal"))
    end
    data = triangulardata(A)
    @inbounds for j in reverse(colsupport(b,1))
        iszero(data[j,j]) && throw(SingularException(j))
        bj = b[j]
        for i in (1:j-1) ∩ colsupport(data,j)
            b[i] -= data[i,j] * bj
        end
    end
    b
end

function materialize!(M::MatLdivVec{<:TriangularLayout{'L','N'}})
    A,b = M.A,M.B
    require_one_based_indexing(A, b)
    n = size(A, 2)
    if !(n == length(b))
        throw(DimensionMismatch("second dimension of left hand side A, $n, and length of right hand side b, $(length(b)), must be equal"))
    end
    data = triangulardata(A)
    @inbounds for j in 1:n
        iszero(data[j,j]) && throw(SingularException(j))
        bj = b[j] = data[j,j] \ b[j]
        for i in (j+1:n) ∩ colsupport(data,j)
            b[i] -= data[i,j] * bj
        end
    end
    b
end

function materialize!(M::BlasMatLdivVec{<:TriangularLayout{'L','U'}})
    A,b = M.A,M.B
    require_one_based_indexing(A, b)
    n = size(A, 2)
    if !(n == length(b))
        throw(DimensionMismatch("second dimension of left hand side A, $n, and length of right hand side b, $(length(b)), must be equal"))
    end
    data = triangulardata(A)
    @inbounds for j in 1:n
        iszero(data[j,j]) && throw(SingularException(j))
        bj = b[j]
        for i in (j+1:n) ∩ colsupport(data,j)
            b[i] -= data[i,j] * bj
        end
    end
    b
end