You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2013/02/03 22:50:38 UTC
[lucy-commits] [2/2] git commit: refs/heads/cfc-tests-rc1 - LUCY-201 Port CFC tests
to C
Updated Branches:
refs/heads/cfc-tests-rc1 [created] 9898c8645
LUCY-201 Port CFC tests to C
Port the Clownfish compiler tests from Perl to C.
Implement a new class CFCTest used to collect results from test runs and
print formatted results in multiple formats: "tap" for TAP output and
"clownfish" for a generic Clownfish format.
All the tests checking exceptions thrown with CFCUtil_die haven't been
ported yet. We first need a way to catch exceptions from C.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/9898c864
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/9898c864
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/9898c864
Branch: refs/heads/cfc-tests-rc1
Commit: 9898c8645b5d94c057626c578fe18fa353f0f4a4
Parents: 3a0c80d
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Jan 23 22:56:33 2013 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sun Feb 3 22:40:31 2013 +0100
----------------------------------------------------------------------
clownfish/compiler/include/CFC.h | 1 +
clownfish/compiler/perl/lib/Clownfish/CFC.pm | 19 +
clownfish/compiler/perl/lib/Clownfish/CFC.xs | 20 +
clownfish/compiler/perl/lib/Clownfish/CFC/Test.pm | 20 +
clownfish/compiler/perl/t/core/001-util.t | 25 +
clownfish/compiler/perl/t/core/050-docucomment.t | 25 +
clownfish/compiler/perl/t/core/051-symbol.t | 25 +
clownfish/compiler/perl/t/core/052-version.t | 25 +
clownfish/compiler/perl/t/core/100-type.t | 25 +
clownfish/compiler/perl/t/core/200-function.t | 25 +
clownfish/compiler/perl/t/core/201-method.t | 25 +
clownfish/compiler/perl/t/core/300-variable.t | 25 +
clownfish/compiler/perl/t/core/301-param_list.t | 25 +
clownfish/compiler/perl/t/core/400-file_spec.t | 25 +
clownfish/compiler/perl/t/core/401-class.t | 25 +
clownfish/compiler/perl/t/core/402-c_block.t | 25 +
clownfish/compiler/perl/t/core/403-parcel.t | 25 +
clownfish/compiler/perl/t/core/404-file.t | 25 +
clownfish/compiler/perl/t/core/500-hierarchy.t | 25 +
clownfish/compiler/perl/t/core/600-parser.t | 25 +
clownfish/compiler/perl/typemap | 1 +
clownfish/compiler/src/CFCTest.c | 490 +++++++++++++++
clownfish/compiler/src/CFCTest.h | 174 ++++++
clownfish/compiler/src/CFCTestCBlock.c | 60 ++
clownfish/compiler/src/CFCTestClass.c | 357 +++++++++++
clownfish/compiler/src/CFCTestDocuComment.c | 107 ++++
clownfish/compiler/src/CFCTestFile.c | 132 ++++
clownfish/compiler/src/CFCTestFileSpec.c | 53 ++
clownfish/compiler/src/CFCTestFunction.c | 76 +++
clownfish/compiler/src/CFCTestHierarchy.c | 231 +++++++
clownfish/compiler/src/CFCTestMethod.c | 251 ++++++++
clownfish/compiler/src/CFCTestParamList.c | 77 +++
clownfish/compiler/src/CFCTestParcel.c | 94 +++
clownfish/compiler/src/CFCTestParser.c | 312 ++++++++++
clownfish/compiler/src/CFCTestSymbol.c | 144 +++++
clownfish/compiler/src/CFCTestType.c | 517 ++++++++++++++++
clownfish/compiler/src/CFCTestUtil.c | 120 ++++
clownfish/compiler/src/CFCTestVariable.c | 100 +++
clownfish/compiler/src/CFCTestVersion.c | 69 ++
39 files changed, 3825 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/include/CFC.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/include/CFC.h b/clownfish/compiler/include/CFC.h
index 93f530e..643263e 100644
--- a/clownfish/compiler/include/CFC.h
+++ b/clownfish/compiler/include/CFC.h
@@ -29,6 +29,7 @@
#include "CFCParcel.h"
#include "CFCParser.h"
#include "CFCSymbol.h"
+#include "CFCTest.h"
#include "CFCType.h"
#include "CFCUtil.h"
#include "CFCVariable.h"
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/lib/Clownfish/CFC.pm
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.pm b/clownfish/compiler/perl/lib/Clownfish/CFC.pm
index 29487be..6635096 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.pm
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.pm
@@ -849,6 +849,25 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.01' ) }
}
}
+{
+ package Clownfish::CFC::Test;
+ BEGIN { push our @ISA, 'Clownfish::CFC::Base' }
+ use Clownfish::CFC::Util qw( verify_args );
+ use Carp;
+
+ my %new_PARAMS = (
+ formatter_name => 'tap',
+ );
+
+ sub new {
+ my ( $either, %args ) = @_;
+ verify_args( \%new_PARAMS, %args ) or confess $@;
+ confess "no subclassing allowed" unless $either eq __PACKAGE__;
+ $args{formatter_name} = 'tap' unless defined $args{formatter_name};
+ return _new( @args{qw( formatter_name )} );
+ }
+}
+
1;
=head1 NAME
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC.xs b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
index 415338e..13ee4d4 100644
--- a/clownfish/compiler/perl/lib/Clownfish/CFC.xs
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC.xs
@@ -2389,3 +2389,23 @@ CODE:
RETVAL = S_cfcbase_to_perlref((CFCBase*)parcel);
OUTPUT: RETVAL
+
+MODULE = Clownfish::CFC PACKAGE = Clownfish::CFC::Test
+
+SV*
+_new(formatter_name)
+ const char *formatter_name;
+CODE:
+ CFCTest *self = CFCTest_new(formatter_name);
+ RETVAL = S_cfcbase_to_perlref(self);
+ CFCBase_decref((CFCBase*)self);
+OUTPUT: RETVAL
+
+int
+run_batch(self, klass)
+ CFCTest *self;
+ const char *klass;
+CODE:
+ RETVAL = CFCTest_run_batch(self, klass);
+OUTPUT: RETVAL
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/lib/Clownfish/CFC/Test.pm
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/lib/Clownfish/CFC/Test.pm b/clownfish/compiler/perl/lib/Clownfish/CFC/Test.pm
new file mode 100644
index 0000000..bebd673
--- /dev/null
+++ b/clownfish/compiler/perl/lib/Clownfish/CFC/Test.pm
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+package Clownfish::CFC::Test;
+use Clownfish::CFC;
+
+1;
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/001-util.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/001-util.t b/clownfish/compiler/perl/t/core/001-util.t
new file mode 100644
index 0000000..b3ad862
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/001-util.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Util');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/050-docucomment.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/050-docucomment.t b/clownfish/compiler/perl/t/core/050-docucomment.t
new file mode 100644
index 0000000..09ad252
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/050-docucomment.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::DocuComment');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/051-symbol.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/051-symbol.t b/clownfish/compiler/perl/t/core/051-symbol.t
new file mode 100644
index 0000000..4209292
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/051-symbol.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Symbol');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/052-version.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/052-version.t b/clownfish/compiler/perl/t/core/052-version.t
new file mode 100644
index 0000000..d5c2f63
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/052-version.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Version');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/100-type.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/100-type.t b/clownfish/compiler/perl/t/core/100-type.t
new file mode 100644
index 0000000..f5a0e24
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/100-type.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Type');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/200-function.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/200-function.t b/clownfish/compiler/perl/t/core/200-function.t
new file mode 100644
index 0000000..d70d2b8
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/200-function.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Function');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/201-method.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/201-method.t b/clownfish/compiler/perl/t/core/201-method.t
new file mode 100644
index 0000000..0f24c25
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/201-method.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Method');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/300-variable.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/300-variable.t b/clownfish/compiler/perl/t/core/300-variable.t
new file mode 100644
index 0000000..c89f830
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/300-variable.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Variable');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/301-param_list.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/301-param_list.t b/clownfish/compiler/perl/t/core/301-param_list.t
new file mode 100644
index 0000000..23cdeb6
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/301-param_list.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::ParamList');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/400-file_spec.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/400-file_spec.t b/clownfish/compiler/perl/t/core/400-file_spec.t
new file mode 100644
index 0000000..c3d25b4
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/400-file_spec.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::FileSpec');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/401-class.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/401-class.t b/clownfish/compiler/perl/t/core/401-class.t
new file mode 100644
index 0000000..6e3b1b2
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/401-class.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Class');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/402-c_block.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/402-c_block.t b/clownfish/compiler/perl/t/core/402-c_block.t
new file mode 100644
index 0000000..f993aa4
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/402-c_block.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::CBlock');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/403-parcel.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/403-parcel.t b/clownfish/compiler/perl/t/core/403-parcel.t
new file mode 100644
index 0000000..1258f6d
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/403-parcel.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Parcel');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/404-file.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/404-file.t b/clownfish/compiler/perl/t/core/404-file.t
new file mode 100644
index 0000000..69c112e
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/404-file.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::File');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/500-hierarchy.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/500-hierarchy.t b/clownfish/compiler/perl/t/core/500-hierarchy.t
new file mode 100644
index 0000000..5b60568
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/500-hierarchy.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Hierarchy');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/t/core/600-parser.t
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/t/core/600-parser.t b/clownfish/compiler/perl/t/core/600-parser.t
new file mode 100644
index 0000000..0311548
--- /dev/null
+++ b/clownfish/compiler/perl/t/core/600-parser.t
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use strict;
+use warnings;
+
+use Clownfish::CFC::Test;
+
+my $test = Clownfish::CFC::Test->new;
+my $passed = $test->run_batch('Clownfish::CFC::Model::Parser');
+
+exit($passed ? 0 : 1);
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/perl/typemap
----------------------------------------------------------------------
diff --git a/clownfish/compiler/perl/typemap b/clownfish/compiler/perl/typemap
index d746181..17be341 100644
--- a/clownfish/compiler/perl/typemap
+++ b/clownfish/compiler/perl/typemap
@@ -29,6 +29,7 @@ CFCParamList* CLOWNFISH_MODEL
CFCParcel* CLOWNFISH_MODEL
CFCParser* CLOWNFISH_TYPE
CFCSymbol* CLOWNFISH_MODEL
+CFCTest* CLOWNFISH_TYPE
CFCType* CLOWNFISH_MODEL
CFCVariable* CLOWNFISH_MODEL
CFCVersion* CLOWNFISH_MODEL
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTest.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.c b/clownfish/compiler/src/CFCTest.c
new file mode 100644
index 0000000..30fc804
--- /dev/null
+++ b/clownfish/compiler/src/CFCTest.c
@@ -0,0 +1,490 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "charmony.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define CFC_NEED_BASE_STRUCT_DEF
+#define CFC_USE_TEST_MACROS
+#include "CFCTest.h"
+#include "CFCBase.h"
+#include "CFCParser.h"
+#include "CFCUtil.h"
+
+typedef struct CFCTestFormatter {
+ void (*batch_prologue)(const CFCTestBatch *batch);
+ void (*vtest_result)(int pass, int test_num, const char *fmt,
+ va_list args);
+ void (*test_comment)(const char *fmt, ...);
+ void (*batch_comment)(const char *fmt, ...);
+ void (*summary)(const CFCTest *test);
+} CFCTestFormatter;
+
+struct CFCTest {
+ CFCBase base;
+ const CFCTestFormatter *formatter;
+ int num_tests;
+ int num_tests_failed;
+ int num_batches;
+ int num_batches_failed;
+ int num_tests_in_batch;
+ int num_failed_in_batch;
+};
+
+static int
+S_do_run_batch(CFCTest *self, const CFCTestBatch *batch);
+
+static void
+S_vtest_true(CFCTest *self, int cond, const char *fmt, va_list args);
+
+static void
+S_format_cfish_batch_prologue(const CFCTestBatch *batch);
+
+static void
+S_format_cfish_vtest_result(int pass, int test_num, const char *fmt,
+ va_list args);
+
+static void
+S_format_cfish_test_comment(const char *fmt, ...);
+
+static void
+S_format_cfish_batch_comment(const char *fmt, ...);
+
+static void
+S_format_cfish_summary(const CFCTest *test);
+
+static void
+S_format_tap_batch_prologue(const CFCTestBatch *batch);
+
+static void
+S_format_tap_vtest_result(int pass, int test_num, const char *fmt,
+ va_list args);
+
+static void
+S_format_tap_test_comment(const char *fmt, ...);
+
+static void
+S_format_tap_batch_comment(const char *fmt, ...);
+
+static void
+S_format_tap_summary(const CFCTest *test);
+
+static const CFCMeta CFCTEST_META = {
+ "Clownfish::CFC::Test",
+ sizeof(CFCTest),
+ (CFCBase_destroy_t)CFCTest_destroy
+};
+
+static const CFCTestFormatter S_formatter_cfish = {
+ S_format_cfish_batch_prologue,
+ S_format_cfish_vtest_result,
+ S_format_cfish_test_comment,
+ S_format_cfish_batch_comment,
+ S_format_cfish_summary
+};
+
+static const CFCTestFormatter S_formatter_tap = {
+ S_format_tap_batch_prologue,
+ S_format_tap_vtest_result,
+ S_format_tap_test_comment,
+ S_format_tap_batch_comment,
+ S_format_tap_summary
+};
+
+static const CFCTestBatch *const S_batches[] = {
+ &CFCTEST_BATCH_UTIL,
+ &CFCTEST_BATCH_DOCU_COMMENT,
+ &CFCTEST_BATCH_SYMBOL,
+ &CFCTEST_BATCH_VERSION,
+ &CFCTEST_BATCH_TYPE,
+ &CFCTEST_BATCH_FUNCTION,
+ &CFCTEST_BATCH_METHOD,
+ &CFCTEST_BATCH_VARIABLE,
+ &CFCTEST_BATCH_PARAM_LIST,
+ &CFCTEST_BATCH_FILE_SPEC,
+ &CFCTEST_BATCH_CLASS,
+ &CFCTEST_BATCH_C_BLOCK,
+ &CFCTEST_BATCH_PARCEL,
+ &CFCTEST_BATCH_FILE,
+ &CFCTEST_BATCH_HIERARCHY,
+ &CFCTEST_BATCH_PARSER,
+ NULL
+};
+
+CFCTest*
+CFCTest_new(const char *formatter_name) {
+ CFCTest *self = (CFCTest*)CFCBase_allocate(&CFCTEST_META);
+ return CFCTest_init(self, formatter_name);
+}
+
+CFCTest*
+CFCTest_init(CFCTest *self, const char *formatter_name) {
+ if (strcmp(formatter_name, "clownfish") == 0) {
+ self->formatter = &S_formatter_cfish;
+ }
+ else if (strcmp(formatter_name, "tap") == 0) {
+ self->formatter = &S_formatter_tap;
+ }
+ else {
+ CFCUtil_die("Unknown formatter name '%s'", formatter_name);
+ }
+
+ self->num_tests = 0;
+ self->num_tests_failed = 0;
+ self->num_batches = 0;
+ self->num_batches_failed = 0;
+ self->num_tests_in_batch = 0;
+ self->num_failed_in_batch = 0;
+
+ return self;
+}
+
+void
+CFCTest_destroy(CFCTest *self) {
+ CFCBase_destroy((CFCBase*)self);
+}
+
+int
+CFCTest_run_all(CFCTest *self) {
+ int failed = 0;
+
+ for (int i = 0; S_batches[i]; ++i) {
+ if (!S_do_run_batch(self, S_batches[i])) { failed = 1; }
+ }
+
+ return !failed;
+}
+
+int
+CFCTest_run_batch(CFCTest *self, const char *name) {
+ for (int i = 0; S_batches[i]; ++i) {
+ const CFCTestBatch *batch = S_batches[i];
+ if (strcmp(batch->name, name) == 0) {
+ return S_do_run_batch(self, batch);
+ }
+ }
+
+ CFCUtil_die("Test batch '%s' not found", name);
+ return 0;
+}
+
+static int
+S_do_run_batch(CFCTest *self, const CFCTestBatch *batch) {
+ self->formatter->batch_prologue(batch);
+
+ batch->run(self);
+
+ int failed = 0;
+ void (*comment)(const char *fmt, ...) = self->formatter->batch_comment;
+
+ if (self->num_failed_in_batch > 0) {
+ failed = 1;
+ comment("%d/%d tests failed.\n", self->num_failed_in_batch,
+ self->num_tests_in_batch);
+ }
+ if (self->num_tests_in_batch != batch->num_planned) {
+ failed = 1;
+ comment("Bad plan: You planned %d tests but ran %d.\n",
+ batch->num_planned, self->num_tests_in_batch);
+ }
+
+ if (failed) {
+ self->num_batches_failed += 1;
+ }
+
+ self->num_batches += 1;
+ self->num_tests_in_batch = 0;
+ self->num_failed_in_batch = 0;
+
+ return !failed;
+}
+
+void
+CFCTest_test_true(CFCTest *self, int cond, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ S_vtest_true(self, cond, fmt, args);
+ va_end(args);
+}
+
+void
+CFCTest_test_string_equals(CFCTest *self, const char *result,
+ const char *expected, const char *fmt, ...) {
+ int cond = (strcmp(result, expected) == 0);
+
+ va_list args;
+ va_start(args, fmt);
+ S_vtest_true(self, cond, fmt, args);
+ va_end(args);
+
+ if (!cond) {
+ self->formatter->test_comment("Expected '%s', got '%s'.\n",
+ expected, result);
+ }
+}
+
+void
+CFCTest_test_int_equals(CFCTest *self, long result, long expected,
+ const char *fmt, ...) {
+ int cond = (result == expected);
+
+ va_list args;
+ va_start(args, fmt);
+ S_vtest_true(self, cond, fmt, args);
+ va_end(args);
+
+ if (!cond) {
+ self->formatter->test_comment("Expected '%ld', got '%ld'.\n",
+ expected, result);
+ }
+}
+
+void
+CFCTest_skip(CFCTest *self, int num) {
+ self->num_tests += num;
+ self->num_tests_in_batch += num;
+}
+
+int
+CFCTest_finish(CFCTest *self) {
+ self->formatter->summary(self);
+
+ return self->num_batches != 0 && self->num_batches_failed == 0;
+}
+
+static void
+S_vtest_true(CFCTest *self, int cond, const char *fmt, va_list args) {
+ self->num_tests += 1;
+ self->num_tests_in_batch += 1;
+
+ if (!cond) {
+ self->num_tests_failed += 1;
+ self->num_failed_in_batch += 1;
+ }
+
+ self->formatter->vtest_result(cond, self->num_tests_in_batch, fmt, args);
+}
+
+static void
+S_format_cfish_batch_prologue(const CFCTestBatch *batch) {
+ printf("Testing %s...\n", batch->name);
+}
+
+static void
+S_format_cfish_vtest_result(int pass, int test_num, const char *fmt,
+ va_list args) {
+ if (!pass) {
+ printf(" Failed test %d: ", test_num);
+ vprintf(fmt, args);
+ printf("\n");
+ }
+}
+
+static void
+S_format_cfish_test_comment(const char *fmt, ...) {
+ printf(" ");
+
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static void
+S_format_cfish_batch_comment(const char *fmt, ...) {
+ printf(" ");
+
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static void
+S_format_cfish_summary(const CFCTest *test) {
+ if (test->num_batches == 0) {
+ printf("No tests planned or run.\n");
+ }
+ else if (test->num_batches_failed == 0) {
+ printf("%d batches passed. %d tests passed.\n",
+ test->num_batches, test->num_tests);
+ printf("Result: PASS\n");
+ }
+ else {
+ printf("%d/%d batches failed. %d/%d tests failed.\n",
+ test->num_batches_failed, test->num_batches,
+ test->num_tests_failed, test->num_tests);
+ printf("Result: FAIL\n");
+ }
+}
+
+static void
+S_format_tap_batch_prologue(const CFCTestBatch *batch) {
+ printf("1..%d\n", batch->num_planned);
+}
+
+static void
+S_format_tap_vtest_result(int pass, int test_num, const char *fmt,
+ va_list args) {
+ const char *result = pass ? "ok" : "not ok";
+ printf("%s %d - ", result, test_num);
+ vprintf(fmt, args);
+ printf("\n");
+}
+
+static void
+S_format_tap_test_comment(const char *fmt, ...) {
+ printf("# ");
+
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static void
+S_format_tap_batch_comment(const char *fmt, ...) {
+ printf("# ");
+
+ va_list args;
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+}
+
+static void
+S_format_tap_summary(const CFCTest *test) {
+}
+
+struct CFCParcel*
+CFCTest_parse_parcel(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Parcel", "result class of '%s'", src);
+ return (struct CFCParcel*)result;
+}
+
+struct CFCType*
+CFCTest_parse_type(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Type", "result class of '%s'", src);
+ return (struct CFCType*)result;
+}
+
+struct CFCVariable*
+CFCTest_parse_variable(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Variable", "result class of '%s'", src);
+ return (struct CFCVariable*)result;
+}
+
+struct CFCParamList*
+CFCTest_parse_param_list(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::ParamList", "result class of '%s'", src);
+ return (struct CFCParamList*)result;
+}
+
+struct CFCFunction*
+CFCTest_parse_function(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Function", "result class of '%s'", src);
+ return (struct CFCFunction*)result;
+}
+
+struct CFCMethod*
+CFCTest_parse_method(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse '%s'", src);
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Method", "result class of '%s'", src);
+ return (struct CFCMethod*)result;
+}
+
+struct CFCClass*
+CFCTest_parse_class(CFCTest *test, CFCParser *parser, const char *src) {
+ CFCBase *result = CFCParser_parse(parser, src);
+ OK(test, result != NULL, "parse class");
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::Class", "result class");
+ return (struct CFCClass*)result;
+}
+
+time_t
+CFCTest_get_file_mtime(const char *path) {
+ struct stat buf;
+ if (stat(path, &buf)) {
+ CFCUtil_die("Can't stat '%s': %s", path, strerror(errno));
+ }
+ return buf.st_mtime;
+}
+
+#if defined(CHY_HAS_UTIME_H)
+
+#include <utime.h>
+
+void
+CFCTest_set_file_times(const char *path, time_t time) {
+ struct utimbuf buf;
+ buf.actime = time;
+ buf.modtime = time;
+ if (utime(path, &buf)) {
+ CFCUtil_die("Can't set file time of '%s': %s", path, strerror(errno));
+ }
+}
+
+#elif defined(CHY_HAS_WINDOWS_H)
+
+#include <windows.h>
+
+void
+CFCTest_set_file_times(const char *path, time_t time) {
+ HANDLE handle = CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, 0, NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ CFCUtil_die("Can't open '%s': %u", path, GetLastError());
+ }
+ uint64_t ticks = 10000000 * (UINT64_C(11644473600) + time);
+ FILETIME file_time;
+ file_time.dwLowDateTime = (DWORD)ticks;
+ file_time.dwHighDateTime = (DWORD)(ticks >> 32);
+ if (!SetFileTime(handle, &file_time, &file_time, &file_time)) {
+ CFCUtil_die("Can't set file time of '%s': %u", path, GetLastError());
+ }
+ CloseHandle(handle);
+}
+
+#else
+
+#error Need either utime.h or windows.h
+
+#endif
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTest.h
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTest.h b/clownfish/compiler/src/CFCTest.h
new file mode 100644
index 0000000..dbb3a17
--- /dev/null
+++ b/clownfish/compiler/src/CFCTest.h
@@ -0,0 +1,174 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Clownfish::CFC::Test - An object to collect results from test runs and
+ * print summaries in multiple formats.
+ */
+
+#ifndef H_CFCTEST
+#define H_CFCTEST
+
+#include <time.h>
+
+#ifdef CFC_USE_TEST_MACROS
+ #define OK CFCTest_test_true
+ #define STR_EQ CFCTest_test_string_equals
+ #define INT_EQ CFCTest_test_int_equals
+#endif
+
+typedef struct CFCTest CFCTest;
+
+typedef struct CFCTestBatch {
+ const char *name;
+ int num_planned;
+ void (*run)(CFCTest *test);
+} CFCTestBatch;
+
+struct CFCClass;
+struct CFCFunction;
+struct CFCMethod;
+struct CFCParamList;
+struct CFCParcel;
+struct CFCParser;
+struct CFCType;
+struct CFCVariable;
+
+/** Create a new test object.
+ *
+ * @param formatter_name Name of the built-in formatter that should be used
+ * to create the output. Supported values are "tap" for TAP output and
+ * "clownfish" for the generic Clownfish format.
+ * @return a new test object.
+ */
+CFCTest*
+CFCTest_new(const char *formatter_name);
+
+CFCTest*
+CFCTest_init(CFCTest *self, const char *formatter_name);
+
+void
+CFCTest_destroy(CFCTest *self);
+
+/** Run all test batches.
+ *
+ * @return true if all tests were successful.
+ */
+int
+CFCTest_run_all(CFCTest *self);
+
+/** Run a test batch by name.
+ *
+ * @param name Name of the test batch.
+ * @return true if all tests in the batch were successful.
+ */
+int
+CFCTest_run_batch(CFCTest *self, const char *name);
+
+/* Collect result of a test.
+ *
+ * @param cond Test condition. True if the test succeeded, false if it failed.
+ * @param fmt printf-like format string describing the test.
+ */
+void
+CFCTest_test_true(CFCTest *self, int cond, const char *fmt, ...);
+
+/* Test strings for equality and collect result.
+ *
+ * @param result Result string to be tested.
+ * @param expected Expected result string.
+ * @param fmt printf-like format string describing the test.
+ */
+void
+CFCTest_test_string_equals(CFCTest *self, const char *result,
+ const char *expected, const char *fmt, ...);
+
+/* Test integers for equality and collect result.
+ *
+ * @param result Result integer to be tested.
+ * @param expected Expected result integer.
+ * @param fmt printf-like format string describing the test.
+ */
+void
+CFCTest_test_int_equals(CFCTest *self, long result, long expected,
+ const char *fmt, ...);
+
+/* Skip tests.
+ *
+ * @param num Number of tests to skip.
+ */
+void
+CFCTest_skip(CFCTest *self, int num);
+
+/* Finish testing.
+ *
+ * @return true if tests were run and all tests were successful.
+ */
+int
+CFCTest_finish(CFCTest *self);
+
+/* Utility functions for tests. */
+
+struct CFCParcel*
+CFCTest_parse_parcel(CFCTest *test, struct CFCParser *parser, const char *src);
+
+struct CFCType*
+CFCTest_parse_type(CFCTest *test, struct CFCParser *parser, const char *src);
+
+struct CFCVariable*
+CFCTest_parse_variable(CFCTest *test, struct CFCParser *parser,
+ const char *src);
+
+struct CFCParamList*
+CFCTest_parse_param_list(CFCTest *test, struct CFCParser *parser,
+ const char *src);
+
+struct CFCFunction*
+CFCTest_parse_function(CFCTest *test, struct CFCParser *parser,
+ const char *src);
+
+struct CFCMethod*
+CFCTest_parse_method(CFCTest *test, struct CFCParser *parser, const char *src);
+
+struct CFCClass*
+CFCTest_parse_class(CFCTest *test, struct CFCParser *parser, const char *src);
+
+time_t
+CFCTest_get_file_mtime(const char *path);
+
+void
+CFCTest_set_file_times(const char *path, time_t time);
+
+/* Test batch structs. */
+
+extern const CFCTestBatch CFCTEST_BATCH_CLASS;
+extern const CFCTestBatch CFCTEST_BATCH_C_BLOCK;
+extern const CFCTestBatch CFCTEST_BATCH_DOCU_COMMENT;
+extern const CFCTestBatch CFCTEST_BATCH_FILE;
+extern const CFCTestBatch CFCTEST_BATCH_FILE_SPEC;
+extern const CFCTestBatch CFCTEST_BATCH_FUNCTION;
+extern const CFCTestBatch CFCTEST_BATCH_HIERARCHY;
+extern const CFCTestBatch CFCTEST_BATCH_METHOD;
+extern const CFCTestBatch CFCTEST_BATCH_PARAM_LIST;
+extern const CFCTestBatch CFCTEST_BATCH_PARCEL;
+extern const CFCTestBatch CFCTEST_BATCH_PARSER;
+extern const CFCTestBatch CFCTEST_BATCH_SYMBOL;
+extern const CFCTestBatch CFCTEST_BATCH_TYPE;
+extern const CFCTestBatch CFCTEST_BATCH_UTIL;
+extern const CFCTestBatch CFCTEST_BATCH_VARIABLE;
+extern const CFCTestBatch CFCTEST_BATCH_VERSION;
+
+#endif /* H_CFCTEST */
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTestCBlock.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestCBlock.c b/clownfish/compiler/src/CFCTestCBlock.c
new file mode 100644
index 0000000..6061d44
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestCBlock.c
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCCBlock.h"
+#include "CFCParser.h"
+#include "CFCTest.h"
+
+static void
+S_run_tests(CFCTest *test);
+
+const CFCTestBatch CFCTEST_BATCH_C_BLOCK = {
+ "Clownfish::CFC::Model::CBlock",
+ 4,
+ S_run_tests
+};
+
+static void
+S_run_tests(CFCTest *test) {
+ CFCParser *parser = CFCParser_new();
+
+ {
+ CFCCBlock *block = CFCCBlock_new("int foo;");
+ STR_EQ(test, CFCCBlock_get_contents(block), "int foo;",
+ "get_contents");
+ CFCBase_decref((CFCBase*)block);
+ }
+
+ {
+ const char *cblock_string =
+ " __C__\n"
+ "#define FOO_BAR 1\n"
+ "__END_C__ ";
+ CFCBase *result = CFCParser_parse(parser, cblock_string);
+ OK(test, result != NULL, "parse cblock");
+ STR_EQ(test, CFCBase_get_cfc_class(result),
+ "Clownfish::CFC::Model::CBlock", "result class of cblock");
+ CFCCBlock *block = (CFCCBlock*)result;
+ STR_EQ(test, CFCCBlock_get_contents(block), "#define FOO_BAR 1\n",
+ "parse embed_c");
+ CFCBase_decref((CFCBase*)block);
+ }
+
+ CFCBase_decref((CFCBase*)parser);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestClass.c b/clownfish/compiler/src/CFCTestClass.c
new file mode 100644
index 0000000..80f008a
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestClass.c
@@ -0,0 +1,357 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCClass.h"
+#include "CFCFileSpec.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCSymbol.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+#include "CFCUtil.h"
+#include "CFCVariable.h"
+
+static void
+S_run_tests(CFCTest *test);
+
+static int
+S_has_symbol(CFCSymbol **symbols, const char *micro_sym);
+
+const CFCTestBatch CFCTEST_BATCH_CLASS = {
+ "Clownfish::CFC::Model::Class",
+ 83,
+ S_run_tests
+};
+
+static void
+S_run_tests(CFCTest *test) {
+ CFCParser *parser = CFCParser_new();
+
+ CFCParcel *neato = CFCParcel_new("Neato", NULL, NULL);
+ CFCFileSpec *file_spec = CFCFileSpec_new(".", "Foo/FooJr", 0);
+
+ CFCVariable *thing;
+ CFCVariable *widget;
+ CFCFunction *tread_water;
+
+ {
+ CFCType *thing_type = CFCTest_parse_type(test, parser, "Thing*");
+ thing = CFCVariable_new(neato, NULL, "Foo", NULL, "thing",
+ thing_type, 0);
+
+ CFCType *widget_type = CFCTest_parse_type(test, parser, "Widget*");
+ widget = CFCVariable_new(NULL, NULL, "Widget", NULL, "widget",
+ widget_type, 0);
+
+ CFCType *return_type = CFCTest_parse_type(test, parser, "void");
+ CFCParamList *param_list
+ = CFCTest_parse_param_list(test, parser, "()");
+ tread_water
+ = CFCFunction_new(neato, NULL, "Foo", NULL, "tread_water",
+ return_type, param_list, NULL, 0);
+
+ CFCBase_decref((CFCBase*)thing_type);
+ CFCBase_decref((CFCBase*)widget_type);
+ CFCBase_decref((CFCBase*)return_type);
+ CFCBase_decref((CFCBase*)param_list);
+ }
+
+ CFCClass *foo
+ = CFCClass_create(neato, NULL, "Foo", NULL, NULL, NULL, NULL, NULL,
+ 0, 0);
+ CFCClass_add_function(foo, tread_water);
+ CFCClass_add_member_var(foo, thing);
+ CFCClass_add_inert_var(foo, widget);
+
+ {
+ CFCClass *should_be_foo = CFCClass_fetch_singleton(neato, "Foo");
+ OK(test, should_be_foo == foo, "fetch_singleton");
+ }
+
+ CFCClass *foo_jr
+ = CFCClass_create(neato, NULL, "Foo::FooJr", NULL, NULL, NULL, NULL,
+ "Foo", 0, 0);
+ CFCClass_add_attribute(foo_jr, "dumpable", "1");
+ OK(test, CFCClass_has_attribute(foo_jr, "dumpable"), "has_attribute");
+ STR_EQ(test, CFCClass_get_struct_sym(foo_jr), "FooJr",
+ "get_struct_sym");
+ STR_EQ(test, CFCClass_full_struct_sym(foo_jr), "neato_FooJr",
+ "full_struct_sym");
+
+ CFCClass *final_foo
+ = CFCClass_create(neato, NULL, "Foo::FooJr::FinalFoo", NULL, NULL, NULL,
+ file_spec, "Foo::FooJr", 1, 0);
+ CFCClass_add_attribute(final_foo, "dumpable", "1");
+ OK(test, CFCClass_final(final_foo), "final");
+ STR_EQ(test, CFCClass_include_h(final_foo), "Foo/FooJr.h",
+ "include_h uses path_part");
+ STR_EQ(test, CFCClass_get_parent_class_name(final_foo), "Foo::FooJr",
+ "get_parent_class_name");
+
+ {
+ CFCParcel *parsed_neato
+ = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+ CFCBase_decref((CFCBase*)parsed_neato);
+ }
+
+ CFCParser_set_class_name(parser, "Foo");
+ CFCMethod *do_stuff
+ = CFCTest_parse_method(test, parser, "void Do_Stuff(Foo *self);");
+ CFCClass_add_method(foo, do_stuff);
+
+ CFCClass_add_child(foo, foo_jr);
+ CFCClass_add_child(foo_jr, final_foo);
+ CFCClass_grow_tree(foo);
+
+ OK(test, CFCClass_get_parent(foo_jr) == foo, "grow_tree, one level" );
+ OK(test, CFCClass_get_parent(final_foo) == foo_jr,
+ "grow_tree, two levels");
+ OK(test, CFCClass_fresh_method(foo, "Do_Stuff") == do_stuff,
+ "fresh_method");
+ OK(test, CFCClass_method(foo_jr, "Do_Stuff") == do_stuff,
+ "inherited method");
+ OK(test, CFCClass_fresh_method(foo_jr, "Do_Stuff") == NULL,
+ "inherited method not 'fresh'");
+ OK(test, CFCMethod_final(CFCClass_method(final_foo, "Do_Stuff")),
+ "Finalize inherited method");
+ OK(test, !CFCMethod_final(CFCClass_method(foo_jr, "Do_Stuff")),
+ "Don't finalize method in parent");
+
+ {
+ CFCVariable **inert_vars = CFCClass_inert_vars(foo);
+ OK(test, inert_vars[0] == widget, "inert_vars[0]");
+ OK(test, inert_vars[1] == NULL, "inert_vars[1]");
+
+ CFCFunction **functions = CFCClass_functions(foo);
+ OK(test, functions[0] == tread_water, "functions[0]");
+ OK(test, functions[1] == NULL, "functions[1]");
+
+ CFCMethod **methods = CFCClass_methods(foo);
+ OK(test, methods[0] == do_stuff, "methods[0]");
+ OK(test, methods[1] == NULL, "methods[1]");
+
+ CFCMethod **fresh_methods = CFCClass_fresh_methods(foo);
+ OK(test, fresh_methods[0] == do_stuff, "fresh_methods[0]");
+ OK(test, fresh_methods[1] == NULL, "fresh_methods[1]");
+
+ CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo);
+ OK(test, fresh_member_vars[0] == thing, "fresh_member_vars[0]");
+ OK(test, fresh_member_vars[1] == NULL, "fresh_member_vars[1]");
+
+ FREEMEM(fresh_methods);
+ FREEMEM(fresh_member_vars);
+ }
+
+ {
+ CFCVariable **member_vars = CFCClass_member_vars(foo_jr);
+ OK(test, member_vars[0] == thing, "member_vars[0]");
+ OK(test, member_vars[1] == NULL, "member_vars[1]");
+
+ CFCFunction **functions = CFCClass_functions(foo_jr);
+ OK(test, functions[0] == NULL, "functions[0]");
+
+ CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo_jr);
+ OK(test, fresh_member_vars[0] == NULL, "fresh_member_vars[0]");
+
+ CFCVariable **inert_vars = CFCClass_inert_vars(foo_jr);
+ OK(test, inert_vars[0] == NULL, "inert_vars[0]");
+
+ FREEMEM(fresh_member_vars);
+ }
+
+ {
+ CFCMethod **fresh_methods = CFCClass_fresh_methods(final_foo);
+ OK(test, fresh_methods[0] == NULL, "fresh_methods[0]");
+ FREEMEM(fresh_methods);
+ }
+
+ {
+ const char *autocode = CFCClass_get_autocode(foo_jr);
+ OK(test, strstr(autocode, "load") != NULL, "autogenerate Dump/Load");
+ }
+
+ {
+ CFCClass **ladder = CFCClass_tree_to_ladder(foo);
+ OK(test, ladder[0] == foo, "ladder[0]");
+ OK(test, ladder[1] == foo_jr, "ladder[1]");
+ OK(test, ladder[2] == final_foo, "ladder[2]");
+ OK(test, ladder[3] == NULL, "ladder[3]");
+ FREEMEM(ladder);
+ }
+
+ {
+ CFCClass *final_class
+ = CFCTest_parse_class(test, parser, "final class Iamfinal { }");
+ OK(test, CFCClass_final(final_class), "class modifer: final");
+ CFCClass *inert_class
+ = CFCTest_parse_class(test, parser, "inert class Iaminert { }");
+ OK(test, CFCClass_inert(inert_class), "class modifer: inert");
+
+ CFCBase_decref((CFCBase*)final_class);
+ CFCBase_decref((CFCBase*)inert_class);
+ }
+
+ {
+ static const char *names[2] = { "Fooble", "Foo::FooJr::FooIII" };
+ for (int i = 0; i < 2; ++i) {
+ const char *name = names[i];
+ char *class_src
+ = CFCUtil_sprintf("class Fu::%s inherits %s { }", name, name);
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ STR_EQ(test, CFCClass_get_parent_class_name(klass), name,
+ "class_inheritance: %s", name);
+ FREEMEM(class_src);
+ CFCBase_decref((CFCBase*)klass);
+ }
+ }
+
+ {
+ const char *class_src =
+ "public class Foo::Foodie cnick Foodie inherits Foo {\n"
+ " private int num;\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+ OK(test, S_has_symbol(member_vars, "num"),
+ "parsed private member var");
+
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ {
+ const char *class_src =
+ "/**\n"
+ " * Bow wow.\n"
+ " *\n"
+ " * Wow wow wow.\n"
+ " */\n"
+ "public class Animal::Dog inherits Animal : lovable : drooly {\n"
+ " public inert Dog* init(Dog *self, CharBuf *name,\n"
+ " CharBuf *fave_food);\n"
+ " inert uint32_t count();\n"
+ " inert uint64_t num_dogs;\n"
+ "\n"
+ " private CharBuf *name;\n"
+ " private bool likes_to_go_fetch;\n"
+ " private void Chase_Tail(Dog *self);\n"
+ "\n"
+ " ChewToy *squishy;\n"
+ "\n"
+ " void Destroy(Dog *self);\n"
+ " public CharBuf* Bark(Dog *self);\n"
+ " public void Eat(Dog *self);\n"
+ " public void Bite(Dog *self, Enemy *enemy);\n"
+ " public Thing *Fetch(Dog *self, Thing *thing);\n"
+ " public final void Bury(Dog *self, Bone *bone);\n"
+ " public Owner *mom;\n"
+ " public abstract incremented nullable Thing*\n"
+ " Scratch(Dog *self);\n"
+ "\n"
+ " int32_t[1] flexible_array_at_end_of_struct;\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+
+ CFCSymbol **inert_vars = (CFCSymbol**)CFCClass_inert_vars(klass);
+ CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+ CFCSymbol **functions = (CFCSymbol**)CFCClass_functions(klass);
+ CFCSymbol **methods = (CFCSymbol**)CFCClass_methods(klass);
+ OK(test, S_has_symbol(inert_vars, "num_dogs"), "parsed inert var");
+ OK(test, S_has_symbol(member_vars, "mom"), "parsed public member var");
+ OK(test, S_has_symbol(member_vars, "squishy"),
+ "parsed parcel member var");
+ OK(test, S_has_symbol(functions, "init"), "parsed function");
+ OK(test, S_has_symbol(methods, "chase_tail"), "parsed private method");
+ OK(test, S_has_symbol(methods, "destroy"), "parsed parcel method");
+ OK(test, S_has_symbol(methods, "bury"), "parsed public method");
+ OK(test, S_has_symbol(methods, "scratch"),
+ "parsed public abstract nullable method");
+
+ CFCMethod *scratch = CFCClass_method(klass, "scratch");
+ OK(test, scratch != NULL, "find method 'scratch'");
+ OK(test, CFCType_nullable(CFCMethod_get_return_type(scratch)),
+ "public abstract incremented nullable flagged as nullable");
+
+ int num_public_methods = 0;
+ for (int i = 0; methods[i]; ++i) {
+ if (CFCSymbol_public(methods[i])) { ++num_public_methods; }
+ }
+ INT_EQ(test, num_public_methods, 6, "pass acl to Method constructor");
+
+ OK(test, CFCClass_has_attribute(klass, "lovable"),
+ "parsed class attribute");
+ OK(test, CFCClass_has_attribute(klass, "drooly"),
+ "parsed second class attribute");
+
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ {
+ const char *class_src =
+ "parcel inert class Rigor::Mortis cnick Mort {\n"
+ " parcel inert void lie_still();\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ OK(test, CFCClass_inert(klass),
+ "inert modifier parsed and passed to constructor");
+
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ {
+ const char *class_src =
+ "final class Ultimo {\n"
+ " /** Throws an error.\n"
+ " */\n"
+ " void Say_Never(Ultimo *self);\n"
+ "}\n";
+ CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
+ OK(test, CFCClass_final(klass), "final class_declaration");
+ CFCBase_decref((CFCBase*)klass);
+ }
+
+ CFCBase_decref((CFCBase*)parser);
+ CFCBase_decref((CFCBase*)neato);
+ CFCBase_decref((CFCBase*)file_spec);
+ CFCBase_decref((CFCBase*)thing);
+ CFCBase_decref((CFCBase*)widget);
+ CFCBase_decref((CFCBase*)tread_water);
+ CFCBase_decref((CFCBase*)foo);
+ CFCBase_decref((CFCBase*)foo_jr);
+ CFCBase_decref((CFCBase*)final_foo);
+ CFCBase_decref((CFCBase*)do_stuff);
+
+ CFCClass_clear_registry();
+ CFCParcel_reap_singletons();
+}
+
+static int
+S_has_symbol(CFCSymbol **symbols, const char *micro_sym) {
+ for (int i = 0; symbols[i]; ++i) {
+ if (strcmp(CFCSymbol_micro_sym(symbols[i]), micro_sym) == 0) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTestDocuComment.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestDocuComment.c b/clownfish/compiler/src/CFCTestDocuComment.c
new file mode 100644
index 0000000..dba5f3c
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestDocuComment.c
@@ -0,0 +1,107 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCDocuComment.h"
+#include "CFCParser.h"
+#include "CFCTest.h"
+#include "CFCUtil.h"
+
+static void
+S_run_tests(CFCTest *test);
+
+const CFCTestBatch CFCTEST_BATCH_DOCU_COMMENT = {
+ "Clownfish::CFC::Model::DocuComment",
+ 15,
+ S_run_tests
+};
+
+static void
+S_run_tests(CFCTest *test) {
+ CFCDocuComment *docucomment;
+
+ docucomment = CFCDocuComment_parse("/** foo. */");
+ OK(test, docucomment != NULL, "parse");
+ CFCBase_decref((CFCBase*)docucomment);
+
+ CFCParser *parser = CFCParser_new();
+ const char *text =
+ "/**\n"
+ " * Brief description. Long description.\n"
+ " *\n"
+ " * More long description.\n"
+ " *\n"
+ " * @param foo A foo.\n"
+ " * @param bar A bar.\n"
+ " *\n"
+ " * @param baz A baz.\n"
+ " * @return a return value.\n"
+ " */\n";
+ CFCBase *result = CFCParser_parse(parser, text);
+ OK(test, result != NULL, "parse with CFCParser");
+ const char *klass = CFCBase_get_cfc_class(result);
+ STR_EQ(test, klass, "Clownfish::CFC::Model::DocuComment", "result class");
+ docucomment = (CFCDocuComment*)result;
+
+ const char *brief_desc = CFCDocuComment_get_brief(docucomment);
+ const char *brief_expect = "Brief description.";
+ STR_EQ(test, brief_desc, brief_expect, "brief description");
+
+ const char *long_desc = CFCDocuComment_get_long(docucomment);
+ const char *long_expect =
+ "Long description.\n"
+ "\n"
+ "More long description.";
+ STR_EQ(test, long_desc, long_expect, "long description");
+
+ const char *description = CFCDocuComment_get_description(docucomment);
+ char *desc_expect = CFCUtil_sprintf("%s %s", brief_expect, long_expect);
+ STR_EQ(test, description, desc_expect, "description");
+ FREEMEM(desc_expect);
+
+ const char **param_names = CFCDocuComment_get_param_names(docucomment);
+ int num_param_names = 0;
+ for (const char **p = param_names; *p; ++p) { ++num_param_names; }
+ INT_EQ(test, num_param_names, 3, "number of param names");
+ const char *param_names_expect[3] = { "foo", "bar", "baz" };
+ for (int i = 0; i < 3; ++i) {
+ STR_EQ(test, param_names[i], param_names_expect[i],
+ "param name %d", i);
+ }
+
+ const char **param_docs = CFCDocuComment_get_param_docs(docucomment);
+ int num_param_docs = 0;
+ for (const char **p = param_docs; *p; ++p) { ++num_param_docs; }
+ INT_EQ(test, num_param_docs, 3, "number of param docs");
+ const char *param_docs_expect[3] = { "A foo.", "A bar.", "A baz." };
+ const char *param_docs_test[3] = {
+ "@param terminated by @",
+ "@param terminated by empty line",
+ "@param terminated next element, @return"
+ };
+ for (int i = 0; i < 3; ++i) {
+ STR_EQ(test, param_docs[i], param_docs_expect[i], param_docs_test[i]);
+ }
+
+ const char *retval = CFCDocuComment_get_retval(docucomment);
+ const char *retval_expect = "a return value.";
+ STR_EQ(test, retval, retval_expect, "retval");
+
+ CFCBase_decref((CFCBase*)docucomment);
+ CFCBase_decref((CFCBase*)parser);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTestFile.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFile.c b/clownfish/compiler/src/CFCTestFile.c
new file mode 100644
index 0000000..2e1edc5
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestFile.c
@@ -0,0 +1,132 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "charmony.h"
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCClass.h"
+#include "CFCFile.h"
+#include "CFCFileSpec.h"
+#include "CFCParser.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+#include "CFCUtil.h"
+#include "CFCVariable.h"
+
+static void
+S_run_tests(CFCTest *test);
+
+const CFCTestBatch CFCTEST_BATCH_FILE = {
+ "Clownfish::CFC::Model::File",
+ 19,
+ S_run_tests
+};
+
+static void
+S_run_tests(CFCTest *test) {
+#define STUFF_THING "Stuff" CHY_DIR_SEP "Thing"
+
+ CFCParser *parser = CFCParser_new();
+ CFCFileSpec *file_spec = CFCFileSpec_new(".", STUFF_THING, 0);
+
+ {
+ const char *string =
+ "parcel Stuff;\n"
+ "class Stuff::Thing {\n"
+ " Foo *foo;\n"
+ " Bar *bar;\n"
+ "}\n"
+ "__C__\n"
+ "int foo;\n"
+ "__END_C__\n";
+ CFCFile *file = CFCParser_parse_file(parser, string, file_spec);
+
+ STR_EQ(test, CFCFile_get_source_dir(file), ".", "get_source_dir");
+ STR_EQ(test, CFCFile_get_path_part(file), STUFF_THING,
+ "get_path_part");
+ OK(test, !CFCFile_included(file), "included");
+
+ STR_EQ(test, CFCFile_guard_name(file), "H_STUFF_THING", "guard_name");
+ STR_EQ(test, CFCFile_guard_start(file),
+ "#ifndef H_STUFF_THING\n#define H_STUFF_THING 1\n",
+ "guard_start");
+ STR_EQ(test, CFCFile_guard_close(file), "#endif /* H_STUFF_THING */\n",
+ "guard_close");
+
+ OK(test, !CFCFile_get_modified(file), "modified false at start");
+ CFCFile_set_modified(file, 1);
+ OK(test, CFCFile_get_modified(file), "set_modified, get_modified");
+
+#define PATH_TO_STUFF_THING \
+ "path" CHY_DIR_SEP \
+ "to" CHY_DIR_SEP \
+ "Stuff" CHY_DIR_SEP \
+ "Thing"
+
+ char *cfh_path = CFCFile_cfh_path(file, "path/to");
+ STR_EQ(test, cfh_path, PATH_TO_STUFF_THING ".cfh", "cfh_path");
+ FREEMEM(cfh_path);
+ char *c_path = CFCFile_c_path(file, "path/to");
+ STR_EQ(test, c_path, PATH_TO_STUFF_THING ".c", "c_path");
+ FREEMEM(c_path);
+ char *h_path = CFCFile_h_path(file, "path/to");
+ STR_EQ(test, h_path, PATH_TO_STUFF_THING ".h", "h_path");
+ FREEMEM(h_path);
+
+ CFCClass **classes = CFCFile_classes(file);
+ OK(test, classes[0] != NULL && classes[1] == NULL,
+ "classes() filters blocks");
+ CFCVariable **member_vars = CFCClass_member_vars(classes[0]);
+ CFCType *foo_type = CFCVariable_get_type(member_vars[0]);
+ STR_EQ(test, CFCType_get_specifier(foo_type), "stuff_Foo",
+ "file production picked up parcel def");
+ CFCType *bar_type = CFCVariable_get_type(member_vars[1]);
+ STR_EQ(test, CFCType_get_specifier(bar_type), "stuff_Bar",
+ "parcel def is sticky");
+
+ CFCBase **blocks = CFCFile_blocks(file);
+ STR_EQ(test, CFCBase_get_cfc_class(blocks[0]),
+ "Clownfish::CFC::Model::Parcel", "blocks[0]");
+ STR_EQ(test, CFCBase_get_cfc_class(blocks[1]),
+ "Clownfish::CFC::Model::Class", "blocks[1]");
+ STR_EQ(test, CFCBase_get_cfc_class(blocks[2]),
+ "Clownfish::CFC::Model::CBlock", "blocks[2]");
+ OK(test, blocks[3] == NULL, "blocks[3]");
+
+ CFCBase_decref((CFCBase*)file);
+ }
+
+ {
+ const char *string =
+ "class Stuff::Thing {\n"
+ " Foo *foo;\n"
+ " Bar *bar;\n"
+ "}\n";
+ CFCFile *file = CFCParser_parse_file(parser, string, file_spec);
+ CFCClass **classes = CFCFile_classes(file);
+ CFCVariable **member_vars = CFCClass_member_vars(classes[0]);
+ CFCType *foo_type = CFCVariable_get_type(member_vars[0]);
+ STR_EQ(test, CFCType_get_specifier(foo_type), "Foo",
+ "file production resets parcel");
+
+ CFCBase_decref((CFCBase*)file);
+ }
+
+ CFCBase_decref((CFCBase*)file_spec);
+ CFCBase_decref((CFCBase*)parser);
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTestFileSpec.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFileSpec.c b/clownfish/compiler/src/CFCTestFileSpec.c
new file mode 100644
index 0000000..7fdb2d8
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestFileSpec.c
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCFileSpec.h"
+#include "CFCTest.h"
+
+static void
+S_run_tests(CFCTest *test);
+
+const CFCTestBatch CFCTEST_BATCH_FILE_SPEC = {
+ "Clownfish::CFC::Model::FileSpec",
+ 4,
+ S_run_tests
+};
+
+static void
+S_run_tests(CFCTest *test) {
+ {
+ CFCFileSpec *file_spec
+ = CFCFileSpec_new("Clownfish/_include", "Stuff/Thing", 0);
+ STR_EQ(test, CFCFileSpec_get_source_dir(file_spec),
+ "Clownfish/_include", "get_source_dir");
+ STR_EQ(test, CFCFileSpec_get_path_part(file_spec),
+ "Stuff/Thing", "get_path_part");
+ OK(test, !CFCFileSpec_included(file_spec), "not included");
+
+ CFCBase_decref((CFCBase*)file_spec);
+ }
+
+ {
+ CFCFileSpec *file_spec
+ = CFCFileSpec_new("Clownfish/_include", "Stuff/Thing", 1);
+ OK(test, CFCFileSpec_included(file_spec), "included");
+
+ CFCBase_decref((CFCBase*)file_spec);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/lucy/blob/9898c864/clownfish/compiler/src/CFCTestFunction.c
----------------------------------------------------------------------
diff --git a/clownfish/compiler/src/CFCTestFunction.c b/clownfish/compiler/src/CFCTestFunction.c
new file mode 100644
index 0000000..4cd6967
--- /dev/null
+++ b/clownfish/compiler/src/CFCTestFunction.c
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_USE_TEST_MACROS
+#include "CFCBase.h"
+#include "CFCFunction.h"
+#include "CFCParamList.h"
+#include "CFCParcel.h"
+#include "CFCParser.h"
+#include "CFCTest.h"
+#include "CFCType.h"
+
+static void
+S_run_tests(CFCTest *test);
+
+const CFCTestBatch CFCTEST_BATCH_FUNCTION = {
+ "Clownfish::CFC::Model::Function",
+ 11,
+ S_run_tests
+};
+
+static void
+S_run_tests(CFCTest *test) {
+ CFCParser *parser = CFCParser_new();
+ CFCParcel *neato_parcel
+ = CFCTest_parse_parcel(test, parser, "parcel Neato;");
+
+ {
+ CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*");
+ CFCParamList *param_list
+ = CFCTest_parse_param_list(test, parser, "(int32_t some_num)");
+ CFCFunction *func
+ = CFCFunction_new(neato_parcel, NULL, "Neato::Foo", "Foo",
+ "return_an_obj", return_type, param_list,
+ NULL, 0);
+ OK(test, func != NULL, "new");
+
+ CFCBase_decref((CFCBase*)return_type);
+ CFCBase_decref((CFCBase*)param_list);
+ CFCBase_decref((CFCBase*)func);
+ }
+
+ {
+ CFCParser_set_class_name(parser, "Neato::Obj");
+ CFCParser_set_class_cnick(parser, "Obj");
+ static const char *func_strings[2] = {
+ "inert int running_count(int biscuit);",
+ "public inert Hash* init_fave_hash(int32_t num_buckets,"
+ " bool o_rly);"
+ };
+ for (int i = 0; i < 2; ++i) {
+ CFCFunction *func
+ = CFCTest_parse_function(test, parser, func_strings[i]);
+ CFCBase_decref((CFCBase*)func);
+ }
+ }
+
+ CFCBase_decref((CFCBase*)neato_parcel);
+ CFCBase_decref((CFCBase*)parser);
+
+ CFCParcel_reap_singletons();
+}
+