blob: 7177d7539fb84e1afb5088513b6a64f5cf6e232e [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/vr/gltf_parser.h"
#include <memory>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/vr/test/paths.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace vr {
// TODO(crbug/770891): Fix GLTF parsing on Windows and reenable the test.
#if defined(OS_WIN)
#define MAYBE(x) DISABLED_##x
#else
#define MAYBE(x) x
#endif
class DataDrivenTest : public testing::Test {
protected:
void SetUp() override { test::GetTestDataPath(&data_dir_); }
base::FilePath data_dir_;
};
class GltfParserTest : public DataDrivenTest {
protected:
std::unique_ptr<base::DictionaryValue> Deserialize(
const base::FilePath& gltf_path);
};
class BinaryGltfParserTest : public DataDrivenTest {};
std::unique_ptr<base::DictionaryValue> GltfParserTest::Deserialize(
const base::FilePath& gltf_path) {
int error_code;
std::string error_msg;
JSONFileValueDeserializer json_deserializer(gltf_path);
auto asset_value = json_deserializer.Deserialize(&error_code, &error_msg);
EXPECT_NE(nullptr, asset_value);
base::DictionaryValue* asset;
EXPECT_TRUE(asset_value->GetAsDictionary(&asset));
asset_value.release();
return std::unique_ptr<base::DictionaryValue>(asset);
}
TEST_F(GltfParserTest, MAYBE(Parse)) {
auto asset =
Deserialize(data_dir_.Append(FILE_PATH_LITERAL("sample_inline.gltf")));
GltfParser parser;
std::vector<std::unique_ptr<gltf::Buffer>> buffers;
std::unique_ptr<gltf::Asset> gltf_model = parser.Parse(*asset, &buffers);
EXPECT_TRUE(gltf_model);
EXPECT_EQ(1u, buffers.size());
const gltf::Buffer* buffer = buffers[0].get();
EXPECT_EQ("HELLO WORLD!", *buffer);
EXPECT_EQ(12u, buffer->length());
const gltf::BufferView* buffer_view = gltf_model->GetBufferView(0);
EXPECT_NE(nullptr, buffer_view);
EXPECT_EQ(nullptr, gltf_model->GetBufferView(1));
EXPECT_EQ(0, buffer_view->buffer);
EXPECT_EQ(20, buffer_view->byte_length);
EXPECT_EQ(10, buffer_view->byte_offset);
EXPECT_EQ(1, buffer_view->target);
const gltf::Accessor* accessor = gltf_model->GetAccessor(0);
EXPECT_NE(nullptr, accessor);
EXPECT_EQ(nullptr, gltf_model->GetAccessor(1));
EXPECT_EQ(buffer_view, accessor->buffer_view);
EXPECT_EQ(10, accessor->byte_offset);
EXPECT_EQ(16, accessor->byte_stride);
EXPECT_EQ(5, accessor->component_type);
EXPECT_EQ(24, accessor->count);
EXPECT_EQ(gltf::VEC3, accessor->type);
const gltf::Mesh* mesh = gltf_model->GetMesh(0);
EXPECT_NE(nullptr, mesh);
EXPECT_EQ(nullptr, gltf_model->GetAccessor(1));
EXPECT_EQ(1u, mesh->primitives.size());
gltf::Mesh::Primitive* primitive = mesh->primitives[0].get();
EXPECT_EQ(1u, primitive->attributes.size());
auto attr_it = primitive->attributes.begin();
EXPECT_EQ("POSITION", attr_it->first);
EXPECT_EQ(accessor, attr_it->second);
EXPECT_EQ(accessor, primitive->indices);
EXPECT_EQ(4, primitive->mode);
const gltf::Node* node_1 = gltf_model->GetNode(0);
const gltf::Node* node_2 = gltf_model->GetNode(1);
EXPECT_NE(nullptr, node_1);
EXPECT_NE(nullptr, node_2);
EXPECT_EQ(nullptr, gltf_model->GetNode(2));
EXPECT_EQ(1u, node_1->children.size());
EXPECT_EQ(0u, node_1->meshes.size());
EXPECT_EQ(node_2, node_1->children[0]);
EXPECT_EQ(0u, node_2->children.size());
EXPECT_EQ(1u, node_2->meshes.size());
EXPECT_EQ(mesh, node_2->meshes[0]);
const gltf::Scene* scene = gltf_model->GetScene(0);
EXPECT_NE(nullptr, scene);
EXPECT_EQ(nullptr, gltf_model->GetNode(2));
EXPECT_EQ(1u, scene->nodes.size());
EXPECT_EQ(node_1, scene->nodes[0]);
EXPECT_EQ(scene, gltf_model->GetMainScene());
}
TEST_F(GltfParserTest, MAYBE(ParseUnknownBuffer)) {
auto asset =
Deserialize(data_dir_.Append(FILE_PATH_LITERAL("sample_inline.gltf")));
GltfParser parser;
std::vector<std::unique_ptr<gltf::Buffer>> buffers;
// Parsing succeeds.
EXPECT_NE(nullptr, parser.Parse(*asset, &buffers));
// Parsing fails when a referenced buffer is removed.
std::unique_ptr<base::Value> value;
asset->Remove("buffers.dummyBuffer", &value);
EXPECT_EQ(nullptr, parser.Parse(*asset, &buffers));
// Parsing fails when the buffer is reinserted with a different ID.
asset->Set("buffers.anotherDummyBuffer", std::move(value));
EXPECT_EQ(nullptr, parser.Parse(*asset, &buffers));
}
TEST_F(GltfParserTest, MAYBE(ParseMissingRequired)) {
auto asset =
Deserialize(data_dir_.Append(FILE_PATH_LITERAL("sample_inline.gltf")));
GltfParser parser;
std::vector<std::unique_ptr<gltf::Buffer>> buffers;
std::unique_ptr<base::Value> value;
asset->Remove("buffers.dummyBuffer.uri", &value);
EXPECT_EQ(nullptr, parser.Parse(*asset, &buffers));
}
TEST_F(GltfParserTest, MAYBE(ParseExternal)) {
auto gltf_path = data_dir_.Append(FILE_PATH_LITERAL("sample_external.gltf"));
GltfParser parser;
std::vector<std::unique_ptr<gltf::Buffer>> buffers;
std::unique_ptr<gltf::Asset> gltf_model = parser.Parse(gltf_path, &buffers);
EXPECT_NE(nullptr, gltf_model);
EXPECT_EQ(1u, buffers.size());
const gltf::Buffer* buffer = buffers[0].get();
EXPECT_NE(nullptr, buffer);
EXPECT_EQ("HELLO WORLD!", *buffer);
EXPECT_EQ(12u, buffer->length());
}
TEST_F(GltfParserTest, MAYBE(ParseExternalNoPath)) {
auto asset =
Deserialize(data_dir_.Append(FILE_PATH_LITERAL("sample_external.gltf")));
GltfParser parser;
std::vector<std::unique_ptr<gltf::Buffer>> buffers;
// Parsing fails when no path is provided.
EXPECT_EQ(nullptr, parser.Parse(*asset, &buffers));
}
TEST_F(BinaryGltfParserTest, MAYBE(ParseBinary)) {
std::string data;
EXPECT_TRUE(base::ReadFileToString(
data_dir_.Append(FILE_PATH_LITERAL("sample.glb")), &data));
base::StringPiece glb_data(data);
std::vector<std::unique_ptr<gltf::Buffer>> buffers;
std::unique_ptr<gltf::Asset> asset =
BinaryGltfParser::Parse(glb_data, &buffers);
EXPECT_TRUE(asset);
EXPECT_EQ(1u, buffers.size());
const gltf::BufferView* buffer_view = asset->GetBufferView(0);
EXPECT_TRUE(buffer_view);
EXPECT_EQ(0, buffer_view->buffer);
}
} // namespace vr