Skip to content
This repository has been archived by the owner on May 2, 2020. It is now read-only.

Commit

Permalink
Add some functor tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelHatherly committed Jun 19, 2015
1 parent ea8f7c3 commit c924737
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/Compiler/compile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ immutable ObjectPair
obj :: Any
end

(==)(a::ObjectPair, b::ObjectPair) = a.mod == b.mod && a.obj == b.obj


"""
Cache data that is independant of output format.
Expand Down
4 changes: 2 additions & 2 deletions src/Functors/Functors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ end

(!){F <: Functor}(functor::F) = Not{F}(functor)

applyf(not::Not, x) = !not.functor(x)
applyf(not::Not, a, b) = !not.functor(a, b)
applyf(not::Not, x) = !applyf(not.functor, x)
applyf(not::Not, a, b) = !applyf(not.functor, a, b)


"""
Expand Down
2 changes: 1 addition & 1 deletion src/Functors/SortBy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import ..Functors:
# No sorting.
immutable Default <: Functor end

applyf(::Default, a, b) = true
applyf(::Default, a, b) = false


# Sort by the string representation of an object.
Expand Down
21 changes: 21 additions & 0 deletions test/Functors/FunctorTestModule.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module FunctorTestModule

"..."
abstract D_1

"..."
type D_2 end

"..."
f_1(x, y = 1) = x

"..."
f_2(x) = x

"..."
g_1(x) = x

"..."
g_2(x) = x

end
157 changes: 157 additions & 0 deletions test/Functors/facts.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
require(joinpath(dirname(@__FILE__), "FunctorTestModule.jl"))

import FunctorTestModule

import Lexicon.Functors:

Functor,
Chained,
GroupBy,
FilterBy,
SortBy,
applyf

import Lexicon.Compiler:

ObjectPair,
makesorter

import Docile.Cache

objectpairs(m) = [ObjectPair(m, o) for o in sort(Cache.objects(m), by = obj -> string(obj))]

name(x::Method) = x.func.code.name
name(d::DataType) = d.name.name

facts("Functors.") do
context("GroupBy.") do

objects = objectpairs(FunctorTestModule)
filename = joinpath(dirname(@__FILE__), "FunctorTestModule.jl")

# Default should return the tuple of line number and filename.
g1 = GroupBy.Default()

for (line, pair) in zip([3, 6, 9, 9, 12, 15, 18], objects)
@fact applyf(g1, pair) => (line, filename)
end

# Custom should group by the symbolic object name.
g2 = GroupBy.Custom(x -> name(x.obj))

for (sym, pair) in zip([:D_1, :D_2, :f_1, :f_1, :f_2, :g_1, :g_2], objects)
@fact applyf(g2, pair) => sym
end
end

context("FilterBy.") do

objects = objectpairs(FunctorTestModule)

# By default we don't filter anything.
f1 = FilterBy.Default()

for obj in objects
@fact applyf(f1, obj) => true
end

# Pick only methods and types, ie. everything from the module in this case.
f2 = FilterBy.Categories(:method, :type)

for obj in objects
@fact applyf(f2, obj) => true
end

# Pick only the types.
f3 = FilterBy.Categories(:type)

for (res, obj) in zip([true, true, false, false, false, false, false], objects)
@fact applyf(f3, obj) => res
end

# Pick only the methods.
f4 = FilterBy.Categories(:method)

for (res, obj) in zip([false, false, true, true, true, true, true], objects)
@fact applyf(f4, obj) => res
end

# Pick none of the available objects.
f5 = FilterBy.Categories(:global, :macro, :bitstype)

for obj in objects
@fact applyf(f5, obj) => false
end

# Pick only objects with a 2 in their name.
f6 = FilterBy.Custom(x -> contains(string(name(x.obj)), "2"))

for (res, obj) in zip([false, true, false, false, true, false, true], objects)
@fact applyf(f6, obj) => res
end
end

context("SortBy.") do

objects = objectpairs(FunctorTestModule)

# Don't sort by default.
s1 = makesorter(SortBy.Default())

for (ind, obj) in zip(1:7, sort(objects, lt = s1))
@fact objects[ind] => obj
end

# Category Ordering, methods then types.
s2 = makesorter(SortBy.CategoryOrder(:method, :function, :type))

for (ind, obj) in zip([3, 4, 5, 6, 7, 1, 2], sort(objects, lt = s2))
@fact objects[ind] => obj
end

# By in reverse by the object's lowercase name.
s3 = SortBy.Custom() do a, b
lowercase(string(name(a.obj))) >= lowercase(string(name(b.obj)))
end |> makesorter

for (ind, obj) in zip([7, 6, 5, 4, 3, 2, 1], sort(objects, lt = s3))
@fact objects[ind] => obj
end
end

context("Compositions.") do
f1 = FilterBy.Categories(:method) & FilterBy.Custom() do x
string(name(x.obj))[1] == 'f'
end
f2 = FilterBy.Categories(:type) | FilterBy.Custom() do x
string(name(x.obj))[1] == 'g'
end
f3 = !FilterBy.Categories(:type)

objects = objectpairs(FunctorTestModule)

# Only methods starting with the letter 'f'.
for (res, obj) in zip([false, false, true, true, true, false, false], objects)
@fact applyf(f1, obj) => res
end
# Types or objects starting with the letter 'g'.
for (res, obj) in zip([true, true, false, false, false, true, true], objects)
@fact applyf(f2, obj) => res
end
# Not objects of category ``:type``.
for (res, obj) in zip([false, false, true, true, true, true, true], objects)
@fact applyf(f3, obj) => res
end

# Sort by the reverse of category ordering methods, then types.
# When the same, then sort by negation of the object name.
c1 = Chained(
!SortBy.CategoryOrder(:method, :type),
!SortBy.StringName()
) |> makesorter

for (ind, obj) in zip([2, 1, 7, 6, 5, 4, 3], sort(objects, lt = c1))
@fact objects[ind] => obj
end
end
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ include(joinpath("Elements", "facts.jl"))
include(joinpath("Queries", "facts.jl"))
include(joinpath("Compiler", "facts.jl"))
include(joinpath("Render", "facts.jl"))
include(joinpath("Functors", "facts.jl"))

isinteractive() || FactCheck.exitstatus()

Expand Down

0 comments on commit c924737

Please sign in to comment.