Skip to content

Commit

Permalink
Tests (partial)
Browse files Browse the repository at this point in the history
Also addresses nits from code review.
Testing will be complete once I figure out how to stub
`eglGetProcAddress` in the tests.
  • Loading branch information
anirudhb committed Aug 27, 2020
1 parent dcde9f2 commit 333457a
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 61 deletions.
1 change: 1 addition & 0 deletions shell/platform/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ executable("flutter_linux_unittests") {
"fl_standard_message_codec_test.cc",
"fl_standard_method_codec_test.cc",
"fl_string_codec_test.cc",
"fl_texture_registrar_test.cc",
"fl_value_test.cc",
"testing/fl_test.cc",
"testing/mock_egl.cc",
Expand Down
18 changes: 1 addition & 17 deletions shell/platform/linux/fl_binary_messenger_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,8 @@
#include "gtest/gtest.h"

#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
#include "flutter/shell/platform/linux/testing/mock_renderer.h"

// Creates a mock engine that responds to platform messages.
static FlEngine* make_mock_engine() {
g_autoptr(FlDartProject) project = fl_dart_project_new();
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
g_autoptr(GError) renderer_error = nullptr;
EXPECT_TRUE(fl_renderer_setup(FL_RENDERER(renderer), &renderer_error));
EXPECT_EQ(renderer_error, nullptr);
g_autoptr(FlEngine) engine = fl_engine_new(project, FL_RENDERER(renderer));
g_autoptr(GError) engine_error = nullptr;
EXPECT_TRUE(fl_engine_start(engine, &engine_error));
EXPECT_EQ(engine_error, nullptr);

return static_cast<FlEngine*>(g_object_ref(engine));
}
#include "flutter/shell/platform/linux/testing/fl_test.h"

// Checks sending nullptr for a message works.
TEST(FlBinaryMessengerTest, SendNullptrMessage) {
Expand Down
9 changes: 5 additions & 4 deletions shell/platform/linux/fl_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// found in the LICENSE file.

#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
#include "flutter/shell/platform/linux/fl_plugin_registrar_private.h"
#include "flutter/shell/platform/linux/fl_renderer.h"
Expand Down Expand Up @@ -600,13 +600,14 @@ void fl_engine_send_mouse_pointer_event(FlEngine* self,
bool fl_engine_mark_texture_frame_available(FlEngine* self,
int64_t texture_id) {
g_return_val_if_fail(FL_IS_ENGINE(self), false);
return !FlutterEngineMarkExternalTextureFrameAvailable(self->engine,
texture_id);
return FlutterEngineMarkExternalTextureFrameAvailable(self->engine,
texture_id) == kSuccess;
}

bool fl_engine_register_external_texture(FlEngine* self, int64_t texture_id) {
g_return_val_if_fail(FL_IS_ENGINE(self), false);
return !FlutterEngineRegisterExternalTexture(self->engine, texture_id);
return FlutterEngineRegisterExternalTexture(self->engine, texture_id) ==
kSuccess;
}

void fl_engine_unregister_external_texture(FlEngine* self, int64_t texture_id) {
Expand Down
75 changes: 37 additions & 38 deletions shell/platform/linux/fl_external_texture_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,35 @@
#include <GL/gl.h>
#include <gmodule.h>

struct {
bool valid;
void (*genTextures)(GLsizei n, GLuint* textures);
void (*bindTexture)(GLenum target, GLuint texture);
void (*texParameteri)(GLenum target, GLenum pname, GLenum param);
void (*texImage2D)(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const void* data);
void (*deleteTextures)(GLsizei n, const GLuint* textures);
} gl;

struct _FlExternalTextureGl {
GLuint gl_texture_id;
FlTextureCallback callback;
struct {
bool valid;
void (*genTextures)(GLsizei n, GLuint* textures);
void (*bindTexture)(GLenum target, GLuint texture);
void (*texParameteri)(GLenum target, GLenum pname, GLenum param);
void (*texImage2D)(GLenum target,
GLint level,
GLint internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const void* data);
void (*deleteTextures)(GLsizei n, const GLuint* textures);
} gl;
void* user_data;
};

G_DEFINE_TYPE(FlExternalTextureGl, fl_external_texture_gl, G_TYPE_OBJECT)

static void fl_external_texture_gl_dispose(GObject* object) {
FlExternalTextureGl* self = FL_EXTERNAL_TEXTURE_GL(object);
if (self->gl.valid) {
self->gl.deleteTextures(1, &self->gl_texture_id);
if (gl.valid) {
gl.deleteTextures(1, &self->gl_texture_id);
}

G_OBJECT_CLASS(fl_external_texture_gl_parent_class)->dispose(object);
Expand Down Expand Up @@ -66,27 +67,27 @@ bool fl_external_texture_gl_populate_texture(
opengl_texture->name = self->gl_texture_id;
opengl_texture->format = GL_RGBA8;
opengl_texture->destruction_callback = nullptr;
opengl_texture->user_data = static_cast<void*>(self);
opengl_texture->user_data = nullptr;
opengl_texture->width = real_width;
opengl_texture->height = real_height;

return true;
}

void fl_external_texture_gl_load_funcs(FlExternalTextureGl* self) {
self->gl.genTextures = reinterpret_cast<void (*)(GLsizei, GLuint*)>(
gl.genTextures = reinterpret_cast<void (*)(GLsizei, GLuint*)>(
eglGetProcAddress("glGenTextures"));
self->gl.bindTexture = reinterpret_cast<void (*)(GLenum, GLuint)>(
gl.bindTexture = reinterpret_cast<void (*)(GLenum, GLuint)>(
eglGetProcAddress("glBindTexture"));
self->gl.texParameteri = reinterpret_cast<void (*)(GLenum, GLenum, GLenum)>(
gl.texParameteri = reinterpret_cast<void (*)(GLenum, GLenum, GLenum)>(
eglGetProcAddress("glTexParameteri"));
self->gl.texImage2D =
gl.texImage2D =
reinterpret_cast<void (*)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint,
GLenum, GLenum, const void*)>(
eglGetProcAddress("glTexImage2D"));
self->gl.deleteTextures = reinterpret_cast<void (*)(GLsizei, const GLuint*)>(
gl.deleteTextures = reinterpret_cast<void (*)(GLsizei, const GLuint*)>(
eglGetProcAddress("glDeleteTextures"));
self->gl.valid = true;
gl.valid = true;
}

bool fl_external_texture_gl_copy_pixel_buffer(FlExternalTextureGl* self,
Expand All @@ -100,24 +101,22 @@ bool fl_external_texture_gl_copy_pixel_buffer(FlExternalTextureGl* self,
*width = pixel_buffer->width;
*height = pixel_buffer->height;

if (!self->gl.valid) {
if (!gl.valid) {
fl_external_texture_gl_load_funcs(self);
}
if (self->gl_texture_id == 0) {
self->gl.genTextures(1, &self->gl_texture_id);
self->gl.bindTexture(GL_TEXTURE_2D, self->gl_texture_id);
self->gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_BORDER);
self->gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_BORDER);
self->gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
self->gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl.genTextures(1, &self->gl_texture_id);
gl.bindTexture(GL_TEXTURE_2D, self->gl_texture_id);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
self->gl.bindTexture(GL_TEXTURE_2D, self->gl_texture_id);
gl.bindTexture(GL_TEXTURE_2D, self->gl_texture_id);
}
self->gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixel_buffer->width,
pixel_buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
pixel_buffer->buffer);
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixel_buffer->width,
pixel_buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
pixel_buffer->buffer);
return true;
}

Expand Down
1 change: 1 addition & 0 deletions shell/platform/linux/fl_external_texture_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_EXTERNAL_TEXURE_GL_H

#include <glib-object.h>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h"

Expand Down
5 changes: 3 additions & 2 deletions shell/platform/linux/fl_texture_registrar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
// found in the LICENSE file.

#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h"

#include <gmodule.h>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_external_texture_gl.h"
#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"

#include <gmodule.h>

struct _FlTextureRegistrar {
GObject parent_instance;

Expand Down
72 changes: 72 additions & 0 deletions shell/platform/linux/fl_texture_registrar_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2020 The Flutter 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 "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_external_texture_gl.h"
#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"
#include "gtest/gtest.h"

#include <gmodule.h>

// Implements eglGetProcAddress but returns dummy functions.
static void* eglGetProcAddress(const char* name) {
return reinterpret_cast<void*>(+[]() {});
}

// Test that registering a texture works.
TEST(FlTextureRegistrarTest, RegisterTexture) {
g_autoptr(FlEngine) engine = make_mock_engine();
FlTextureRegistrar* registrar = fl_texture_registrar_new(engine);
fl_texture_registrar_register_texture(registrar, nullptr, nullptr);
}

// Test that unregistering a texture works.
TEST(FlTextureRegistrarTest, UnregisterTexture) {
g_autoptr(FlEngine) engine = make_mock_engine();
FlTextureRegistrar* registrar = fl_texture_registrar_new(engine);
int64_t id =
fl_texture_registrar_register_texture(registrar, nullptr, nullptr);
fl_texture_registrar_unregister_texture(registrar, id);
}

// Test that marking a texture frame available works.
TEST(FlTextureRegistrarTest, MarkTextureFrameAvailable) {
g_autoptr(FlEngine) engine = make_mock_engine();
FlTextureRegistrar* registrar = fl_texture_registrar_new(engine);
int64_t id =
fl_texture_registrar_register_texture(registrar, nullptr, nullptr);
fl_texture_registrar_mark_texture_frame_available(registrar, id);
}

// TODO: Re-enable after figuring out how to stub out eglGetProcAddress.
// Also write tests for #FlExternalTextureGl as well.
//
// Test that populating an OpenGL texture works.
// TEST(FlTextureRegistrarTest, PopulateTexture) {
// g_autoptr(FlEngine) engine = make_mock_engine();
// FlTextureRegistrar* registrar = fl_texture_registrar_new(engine);
// const uint8_t buffer[] = {0x7a, 0x8a, 0x9a, 0xaa};
// FlPixelBuffer pixel_buffer;
// pixel_buffer.buffer = buffer;
// pixel_buffer.width = 2;
// pixel_buffer.height = 2;
// FlTextureCallback callback = [](size_t width, size_t height,
// void* user_data) -> const FlPixelBuffer* {
// FlPixelBuffer* pixel_buffer = static_cast<FlPixelBuffer*>(user_data);
// EXPECT_EQ(width, pixel_buffer->width);
// EXPECT_EQ(height, pixel_buffer->height);
// return pixel_buffer;
// };
// int64_t id =
// fl_texture_registrar_register_texture(registrar, callback,
// &pixel_buffer);
// FlutterOpenGLTexture opengl_texture;
// EXPECT_TRUE(fl_texture_registrar_populate_texture(
// registrar, id, pixel_buffer.width, pixel_buffer.height,
// &opengl_texture));
// EXPECT_EQ(opengl_texture.width, pixel_buffer.width);
// EXPECT_EQ(opengl_texture.height, pixel_buffer.height);
// }
22 changes: 22 additions & 0 deletions shell/platform/linux/testing/fl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

#include "flutter/shell/platform/linux/testing/fl_test.h"

#include <gmodule.h>

// Doesn't work if included in the next block.
#include "gtest/gtest.h"

#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/testing/mock_renderer.h"

static uint8_t hex_digit_to_int(char value) {
if (value >= '0' && value <= '9')
return value - '0';
Expand Down Expand Up @@ -39,3 +47,17 @@ gchar* bytes_to_hex_string(GBytes* bytes) {
g_string_append_printf(hex_string, "%02x", data[i]);
return g_string_free(hex_string, FALSE);
}

FlEngine* make_mock_engine() {
g_autoptr(FlDartProject) project = fl_dart_project_new();
g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
g_autoptr(GError) renderer_error = nullptr;
EXPECT_EQ(fl_renderer_setup(FL_RENDERER(renderer), &renderer_error), TRUE);
EXPECT_EQ(renderer_error, nullptr);
g_autoptr(FlEngine) engine = fl_engine_new(project, FL_RENDERER(renderer));
g_autoptr(GError) engine_error = nullptr;
EXPECT_EQ(fl_engine_start(engine, &engine_error), TRUE);
EXPECT_EQ(engine_error, nullptr);

return static_cast<FlEngine*>(g_object_ref(engine));
}
5 changes: 5 additions & 0 deletions shell/platform/linux/testing/fl_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef FLUTTER_SHELL_PLATFORM_LINUX_FL_TEST_H_
#define FLUTTER_SHELL_PLATFORM_LINUX_FL_TEST_H_

#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"

#include <glib.h>
#include <stdint.h>

Expand All @@ -18,6 +20,9 @@ GBytes* hex_string_to_bytes(const gchar* hex_string);
// Helper function to convert GBytes into a hexadecimal string (e.g. "01feab")
gchar* bytes_to_hex_string(GBytes* bytes);

// Creates a mock engine that responds to platform messages.
FlEngine* make_mock_engine();

G_END_DECLS

#endif // FLUTTER_SHELL_PLATFORM_LINUX_FL_TEST_H_
16 changes: 16 additions & 0 deletions shell/platform/linux/testing/mock_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,19 @@
#include "gtest/gtest.h"

#include <string.h>
#include <iterator>
#include <unordered_map>

struct _FlutterEngineTexture {
bool hasNewFrame;
};

struct _FlutterEngine {
bool running;
FlutterPlatformMessageCallback platform_message_callback;
FlutterTaskRunnerPostTaskCallback platform_post_task_callback;
void* user_data;
std::unordered_map<int64_t, _FlutterEngineTexture> textures;

_FlutterEngine(FlutterPlatformMessageCallback platform_message_callback,
FlutterTaskRunnerPostTaskCallback platform_post_task_callback,
Expand Down Expand Up @@ -393,17 +400,26 @@ FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine)
FlutterEngineResult FlutterEngineRegisterExternalTexture(
FLUTTER_API_SYMBOL(FlutterEngine) engine,
int64_t texture_identifier) {
_FlutterEngineTexture texture;
texture.hasNewFrame = false;
engine->textures[texture_identifier] = texture;
return kSuccess;
}

FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable(
FLUTTER_API_SYMBOL(FlutterEngine) engine,
int64_t texture_identifier) {
auto val = engine->textures.find(texture_identifier);
if (val == std::end(engine->textures)) {
return kInvalidArguments;
}
val->second.hasNewFrame = true;
return kSuccess;
}

FlutterEngineResult FlutterEngineUnregisterExternalTexture(
FLUTTER_API_SYMBOL(FlutterEngine) engine,
int64_t texture_identifier) {
engine->textures.erase(texture_identifier);
return kSuccess;
}

0 comments on commit 333457a

Please sign in to comment.