summaryrefslogtreecommitdiffstats
path: root/o3d/compiler/technique/technique_parser_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/compiler/technique/technique_parser_test.cc')
-rw-r--r--o3d/compiler/technique/technique_parser_test.cc414
1 files changed, 414 insertions, 0 deletions
diff --git a/o3d/compiler/technique/technique_parser_test.cc b/o3d/compiler/technique/technique_parser_test.cc
new file mode 100644
index 0000000..ea2ca0a
--- /dev/null
+++ b/o3d/compiler/technique/technique_parser_test.cc
@@ -0,0 +1,414 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//
+// Test program to exercise the Technique Antlr grammar using both files and
+// in-memory string buffers.
+
+#include "tests/common/win/testing_common.h"
+#include "compiler/technique/technique_parser.h"
+
+namespace o3d {
+
+// classes ---------------------------------------------------------------------
+
+class TechniqueParserTest : public testing::Test {
+ protected:
+ virtual void SetUp();
+ virtual void TearDown();
+ private:
+};
+
+void TechniqueParserTest::SetUp() {
+}
+
+void TechniqueParserTest::TearDown() {
+}
+
+// globals ---------------------------------------------------------------------
+
+char simple_fx_source[] =
+"float4x4 worldViewProj : WORLDVIEWPROJECTION; \
+void vs(in float4 pos, out float4 opos) { \
+ opos = mul(pos, worldViewProj); \
+} \
+float4 fs(): COLOR { \
+ return float3(0.33f, 0.57f, 0.10f); \
+} \
+technique t1 { \
+ pass p0 { \
+ VertexShader = compile vs_2_0 vs(); \
+ PixelShader = compile ps_2_0 fs(); \
+ } \
+} \
+";
+
+char lambert_fx_source[] =
+"struct a2v { \
+ float4 pos : POSITION; \
+ float3 normal : NORMAL; \
+}; \
+ \
+struct v2f { \
+ float4 pos : POSITION; \
+ float3 n : TEXCOORD0; \
+ float3 l : TEXCOORD1; \
+}; \
+ \
+float4x4 worldViewProj : WorldViewProjection; \
+float4x4 world : World; \
+float4x4 worldIT : WorldInverseTranspose; \
+float3 lightWorldPos; \
+float4 lightColor; \
+ \
+v2f vsMain(a2v IN) { \
+ v2f OUT; \
+ OUT.pos = mul(IN.pos, worldViewProj); \
+ OUT.n = mul(float4(IN.normal,0), worldIT).xyz; \
+ OUT.l = lightWorldPos-mul(IN.pos, world).xyz; \
+ return OUT; \
+} \
+ \
+float4 fsMain(v2f IN): COLOR { \
+ float3 l=normalize(IN.l); \
+ float3 n=normalize(IN.n); \
+ float4 litR=lit(dot(n,l),0,0); \
+ return emissive+lightColor*(ambient+diffuse*litR.y); \
+} \
+ \
+technique { \
+ pass p0 { \
+ VertexShader = compile vs_2_0 vsMain(); \
+ PixelShader = compile ps_2_0 fsMain(); \
+ } \
+} \
+";
+
+// -----------------------------------------------------------------------------
+
+TEST_F(TechniqueParserTest, ParseSimpleFXFromFile) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/simple.fx";
+ EXPECT_TRUE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_LT(0, static_cast<int>(technique_list.size()));
+ ASSERT_EQ(1, technique_list.size());
+ EXPECT_EQ("t1", technique_list[0].name);
+ ASSERT_EQ(0, technique_list[0].annotation.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("p0", technique_list[0].pass[0].name);
+ ASSERT_EQ(0, technique_list[0].pass[0].annotation.size());
+ EXPECT_EQ("vs", technique_list[0].pass[0].vertex_shader_entry);
+ EXPECT_EQ("vs_2_0", technique_list[0].pass[0].vertex_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_arguments);
+ EXPECT_EQ("fs", technique_list[0].pass[0].fragment_shader_entry);
+ EXPECT_EQ("ps_2_0", technique_list[0].pass[0].fragment_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_arguments);
+ ASSERT_EQ(0, technique_list[0].pass[0].state_assignment.size());
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseSimpleFXFromString) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ EXPECT_TRUE(ParseFxString(simple_fx_source,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_LT(0, static_cast<int>(technique_list.size()));
+ ASSERT_EQ(1, technique_list.size());
+ EXPECT_EQ("t1", technique_list[0].name);
+ ASSERT_EQ(0, technique_list[0].annotation.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("p0", technique_list[0].pass[0].name);
+ ASSERT_EQ(0, technique_list[0].pass[0].annotation.size());
+ EXPECT_EQ("vs", technique_list[0].pass[0].vertex_shader_entry);
+ EXPECT_EQ("vs_2_0", technique_list[0].pass[0].vertex_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_arguments);
+ EXPECT_EQ("fs", technique_list[0].pass[0].fragment_shader_entry);
+ EXPECT_EQ("ps_2_0", technique_list[0].pass[0].fragment_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_arguments);
+ ASSERT_EQ(0, technique_list[0].pass[0].state_assignment.size());
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseLambertFXFromFile) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/lambert.fx";
+ EXPECT_TRUE(ParseFxFile(filepath.c_str(),
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_LT(0, static_cast<int>(technique_list.size()));
+ ASSERT_EQ(1, technique_list.size());
+ EXPECT_EQ("", technique_list[0].name);
+ ASSERT_EQ(0, technique_list[0].annotation.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("p0", technique_list[0].pass[0].name);
+ ASSERT_EQ(0, technique_list[0].pass[0].annotation.size());
+ EXPECT_EQ("vsMain", technique_list[0].pass[0].vertex_shader_entry);
+ EXPECT_EQ("vs_2_0", technique_list[0].pass[0].vertex_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_arguments);
+ EXPECT_EQ("fsMain", technique_list[0].pass[0].fragment_shader_entry);
+ EXPECT_EQ("ps_2_0", technique_list[0].pass[0].fragment_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_arguments);
+ ASSERT_EQ(0, technique_list[0].pass[0].state_assignment.size());
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseLambertFXFromString) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ EXPECT_TRUE(ParseFxString(lambert_fx_source,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_LT(0, static_cast<int>(technique_list.size()));
+ ASSERT_EQ(1, technique_list.size());
+ EXPECT_EQ("", technique_list[0].name);
+ ASSERT_EQ(0, technique_list[0].annotation.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("p0", technique_list[0].pass[0].name);
+ ASSERT_EQ(0, technique_list[0].pass[0].annotation.size());
+ EXPECT_EQ("vsMain", technique_list[0].pass[0].vertex_shader_entry);
+ EXPECT_EQ("vs_2_0", technique_list[0].pass[0].vertex_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_arguments);
+ EXPECT_EQ("fsMain", technique_list[0].pass[0].fragment_shader_entry);
+ EXPECT_EQ("ps_2_0", technique_list[0].pass[0].fragment_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_arguments);
+ ASSERT_EQ(0, technique_list[0].pass[0].state_assignment.size());
+ ASSERT_EQ(0, sampler_list.size());
+}
+
+
+
+// Test the longer shaders from files ------------------------------------------
+
+TEST_F(TechniqueParserTest, ParseNoShaderFXFromFile) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/noshader.fx";
+ EXPECT_TRUE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_LT(0, static_cast<int>(technique_list.size()));
+ ASSERT_EQ(1, technique_list.size());
+ EXPECT_EQ("t1", technique_list[0].name);
+ ASSERT_EQ(0, technique_list[0].annotation.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("p0", technique_list[0].pass[0].name);
+ ASSERT_EQ(0, technique_list[0].pass[0].annotation.size());
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_entry);
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].vertex_shader_arguments);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_entry);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_profile);
+ EXPECT_EQ("", technique_list[0].pass[0].fragment_shader_arguments);
+ ASSERT_EQ(4, technique_list[0].pass[0].state_assignment.size());
+ EXPECT_EQ("ZEnable", technique_list[0].pass[0].state_assignment[0].name);
+ EXPECT_EQ("true", technique_list[0].pass[0].state_assignment[0].value);
+ EXPECT_EQ("ZWriteEnable", technique_list[0].pass[0].state_assignment[1].name);
+ EXPECT_EQ("true", technique_list[0].pass[0].state_assignment[1].value);
+ EXPECT_EQ("ZFunc", technique_list[0].pass[0].state_assignment[2].name);
+ EXPECT_EQ("LessEqual", technique_list[0].pass[0].state_assignment[2].value);
+ EXPECT_EQ("CullMode", technique_list[0].pass[0].state_assignment[3].name);
+ EXPECT_EQ("None", technique_list[0].pass[0].state_assignment[3].value);
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseNoTechniqueFXFromFile) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/notechnique.fx";
+ EXPECT_TRUE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(0, technique_list.size());
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseFurFXFromFile) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/fur.fx";
+ EXPECT_TRUE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ ASSERT_EQ(1, technique_list.size());
+ EXPECT_EQ(1, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseShadowMapFXFromFile) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/shadow_map.fx";
+ EXPECT_TRUE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ ASSERT_EQ(2, technique_list.size());
+ EXPECT_EQ(2, sampler_list.size());
+}
+
+
+
+// Tests of error cases --------------------------------------------------------
+
+TEST_F(TechniqueParserTest, ParseEmptyString) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String empty_fx_source = "";
+ EXPECT_TRUE(ParseFxString(empty_fx_source,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(0, technique_list.size());
+ EXPECT_EQ(String(""), shader_source);
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseInvalidString) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String invalid_fx_source = "$%^~ This is an invalid shader.";
+ EXPECT_FALSE(ParseFxString(invalid_fx_source,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(0, technique_list.size());
+ EXPECT_EQ(0, sampler_list.size());
+ // TODO: make sure the string was rejected as an invalid HLSL
+ // program and test the parser errors.
+}
+
+TEST_F(TechniqueParserTest, ParseInvalidFilename) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/invalid_filename.fx";
+ EXPECT_FALSE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(technique_list.size(), 0);
+ EXPECT_EQ(shader_source, String(""));
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseInvalidPassIdentifier) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String invalid_pass_identifier_source = "technique { pass pass { } };";
+ EXPECT_FALSE(ParseFxString(invalid_pass_identifier_source,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(1, technique_list.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("", technique_list[0].pass[0].name);
+ EXPECT_EQ(shader_source, String(""));
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseInvalidStateName) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ // NOTE: "FragmentShader" should read "FragmentProgram" or "PixelShader".
+ String invalid_pass_identifier_source =
+ "technique { pass { FragmentShader = compile ps_2_0 nothing(); } };";
+ EXPECT_FALSE(ParseFxString(invalid_pass_identifier_source,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(1, technique_list.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ EXPECT_EQ("", technique_list[0].pass[0].name);
+ EXPECT_EQ(shader_source, String(""));
+ EXPECT_EQ(0, sampler_list.size());
+}
+
+TEST_F(TechniqueParserTest, ParseSampler) {
+ String shader_source, error_string;
+ TechniqueDeclarationList technique_list;
+ SamplerStateList sampler_list;
+ String filepath = *g_program_path + "/unittest_data/sampler_test.fx";
+ EXPECT_TRUE(ParseFxFile(filepath,
+ &shader_source,
+ &sampler_list,
+ &technique_list,
+ &error_string));
+ EXPECT_EQ(1, technique_list.size());
+ ASSERT_EQ(1, technique_list[0].pass.size());
+ ASSERT_EQ(1, sampler_list.size());
+ EXPECT_EQ("Tex0", sampler_list[0].texture);
+ EXPECT_EQ("Linear", sampler_list[0].min_filter);
+ EXPECT_EQ("Point", sampler_list[0].mag_filter);
+ EXPECT_EQ("None", sampler_list[0].mip_filter);
+ EXPECT_EQ("Mirror", sampler_list[0].address_u);
+ EXPECT_EQ("Wrap", sampler_list[0].address_v);
+ EXPECT_EQ("Clamp", sampler_list[0].address_w);
+ EXPECT_EQ("16", sampler_list[0].max_anisotropy);
+ EXPECT_EQ("float4(1.0, 0.0, 0.0, 1.0)", sampler_list[0].border_color);
+}
+
+} // namespace o3d