[1/4] dwrite: Added initial test code for text analyzer tests

Nikolay Sivov nsivov at codeweavers.com
Mon Oct 29 07:32:20 CDT 2012


Added initial test code for text analyzer tests
-------------- next part --------------
>From 9611921dc45a074d7534f53077514fc01aab3e6c Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun, 28 Oct 2012 13:21:13 -0400
Subject: [PATCH 2/4] Added initial test code for text analyzer tests

---
 dlls/dwrite/tests/Makefile.in |    1 +
 dlls/dwrite/tests/analyzer.c  |  472 +++++++++++++++++++++++++++++++++++++++++
 dlls/dwrite/tests/font.c      |    2 -
 3 files changed, 473 insertions(+), 2 deletions(-)
 create mode 100644 dlls/dwrite/tests/analyzer.c

diff --git a/dlls/dwrite/tests/Makefile.in b/dlls/dwrite/tests/Makefile.in
index 9009a8f..7d67067 100644
--- a/dlls/dwrite/tests/Makefile.in
+++ b/dlls/dwrite/tests/Makefile.in
@@ -2,6 +2,7 @@ TESTDLL = dwrite.dll
 IMPORTS = dwrite gdi32
 
 C_SRCS = \
+	analyzer.c \
 	font.c \
 	layout.c
 
diff --git a/dlls/dwrite/tests/analyzer.c b/dlls/dwrite/tests/analyzer.c
new file mode 100644
index 0000000..a00f20e
--- /dev/null
+++ b/dlls/dwrite/tests/analyzer.c
@@ -0,0 +1,472 @@
+/*
+ *    Text analyzing tests
+ *
+ * Copyright 2012 Nikolay Sivov for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <assert.h>
+
+#include "initguid.h"
+#include "windows.h"
+#include "dwrite.h"
+
+#include "wine/test.h"
+
+static IDWriteFactory *factory;
+
+enum analysis_kind {
+    ScriptAnalysis,
+    LastKind
+};
+
+static const char *get_analysis_kind_name(enum analysis_kind kind)
+{
+    switch (kind)
+    {
+    case ScriptAnalysis:
+        return "ScriptAnalysis";
+    default:
+        return "unknown";
+    }
+}
+
+struct script_analysis {
+    UINT32 pos;
+    UINT32 len;
+    DWRITE_SCRIPT_ANALYSIS a;
+};
+
+struct call_entry {
+    enum analysis_kind kind;
+    struct script_analysis sa;
+};
+
+struct testcontext {
+    enum analysis_kind kind;
+    int todo;
+    int *failcount;
+    const char *file;
+    int line;
+};
+
+struct call_sequence
+{
+    int count;
+    int size;
+    struct call_entry *sequence;
+};
+
+#define NUM_CALL_SEQUENCES    1
+#define ANALYZER_ID 0
+static struct call_sequence *sequences[NUM_CALL_SEQUENCES];
+static struct call_sequence *expected_seq[1];
+
+static void add_call(struct call_sequence **seq, int sequence_index, const struct call_entry *call)
+{
+    struct call_sequence *call_seq = seq[sequence_index];
+
+    if (!call_seq->sequence)
+    {
+        call_seq->size = 10;
+        call_seq->sequence = HeapAlloc(GetProcessHeap(), 0,
+                                      call_seq->size * sizeof (struct call_entry));
+    }
+
+    if (call_seq->count == call_seq->size)
+    {
+        call_seq->size *= 2;
+        call_seq->sequence = HeapReAlloc(GetProcessHeap(), 0,
+                                        call_seq->sequence,
+                                        call_seq->size * sizeof (struct call_entry));
+    }
+
+    assert(call_seq->sequence);
+
+    call_seq->sequence[call_seq->count++] = *call;
+}
+
+static inline void flush_sequence(struct call_sequence **seg, int sequence_index)
+{
+    struct call_sequence *call_seq = seg[sequence_index];
+
+    HeapFree(GetProcessHeap(), 0, call_seq->sequence);
+    call_seq->sequence = NULL;
+    call_seq->count = call_seq->size = 0;
+}
+
+static inline void flush_sequences(struct call_sequence **seq, int n)
+{
+    int i;
+    for (i = 0; i < n; i++)
+        flush_sequence(seq, i);
+}
+
+static void init_call_sequences(struct call_sequence **seq, int n)
+{
+    int i;
+
+    for (i = 0; i < n; i++)
+        seq[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct call_sequence));
+}
+
+static void test_uint(UINT32 actual, UINT32 expected, const char *name, const struct testcontext *ctxt)
+{
+    if (expected != actual && ctxt->todo)
+    {
+        (*ctxt->failcount)++;
+        ok_(ctxt->file, ctxt->line) (0, "%s: \"%s\" expecting %u, got %u\n", get_analysis_kind_name(ctxt->kind), name, expected, actual);
+    }
+    else
+        ok_(ctxt->file, ctxt->line) (expected == actual, "%s: \"%s\" expecting %u, got %u\n", get_analysis_kind_name(ctxt->kind), name,
+            expected, actual);
+}
+
+static void ok_sequence_(struct call_sequence **seq, int sequence_index,
+    const struct call_entry *expected, const char *context, int todo,
+    const char *file, int line)
+{
+    struct call_sequence *call_seq = seq[sequence_index];
+    static const struct call_entry end_of_sequence = { LastKind };
+    const struct call_entry *actual, *sequence;
+    int failcount = 0;
+    struct testcontext ctxt;
+
+    add_call(seq, sequence_index, &end_of_sequence);
+
+    sequence = call_seq->sequence;
+    actual = sequence;
+
+    ctxt.failcount = &failcount;
+    ctxt.todo = todo;
+    ctxt.file = file;
+    ctxt.line = line;
+
+    while (expected->kind != LastKind && actual->kind != LastKind)
+    {
+        if (expected->kind == actual->kind)
+        {
+            ctxt.kind = expected->kind;
+
+            switch (actual->kind)
+            {
+            case ScriptAnalysis:
+            {
+                const struct script_analysis *sa_act = &actual->sa;
+                const struct script_analysis *sa_exp = &expected->sa;
+
+                test_uint(sa_act->pos, sa_exp->pos, "position", &ctxt);
+                test_uint(sa_act->len, sa_exp->len, "length", &ctxt);
+                test_uint(sa_act->a.script, sa_exp->a.script, "script", &ctxt);
+
+                break;
+            }
+            default:
+                ok(0, "%s: callback not handled, %s\n", context, get_analysis_kind_name(actual->kind));
+            }
+            expected++;
+            actual++;
+        }
+        else if (todo)
+        {
+            failcount++;
+            todo_wine
+            {
+                ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
+                    context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
+            }
+
+            flush_sequence(seq, sequence_index);
+            return;
+        }
+        else
+        {
+            ok_(file, line) (0, "%s: call %s was expected, but got call %s instead\n",
+                context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
+            expected++;
+            actual++;
+        }
+    }
+
+    if (todo)
+    {
+        todo_wine
+        {
+            if (expected->kind != LastKind || actual->kind != LastKind)
+            {
+                failcount++;
+                ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
+                    context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
+            }
+        }
+    }
+    else if (expected->kind != LastKind || actual->kind != LastKind)
+    {
+        ok_(file, line) (0, "%s: the call sequence is not complete: expected %s - actual %s\n",
+            context, get_analysis_kind_name(expected->kind), get_analysis_kind_name(actual->kind));
+    }
+
+    if (todo && !failcount) /* succeeded yet marked todo */
+    {
+        todo_wine
+        {
+            ok_(file, line)(1, "%s: marked \"todo_wine\" but succeeds\n", context);
+        }
+    }
+
+    flush_sequence(seq, sequence_index);
+}
+
+#define ok_sequence(seq, index, exp, contx, todo) \
+        ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
+
+static HRESULT WINAPI analysissink_QueryInterface(IDWriteTextAnalysisSink *iface, REFIID riid, void **obj)
+{
+    if (IsEqualIID(riid, &IID_IDWriteTextAnalysisSink) || IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        return S_OK;
+    }
+
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI analysissink_AddRef(IDWriteTextAnalysisSink *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI analysissink_Release(IDWriteTextAnalysisSink *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI analysissink_SetScriptAnalysis(IDWriteTextAnalysisSink *iface,
+    UINT32 position, UINT32 length, DWRITE_SCRIPT_ANALYSIS const* scriptanalysis)
+{
+    struct call_entry entry;
+
+    entry.kind = ScriptAnalysis;
+    entry.sa.pos = position;
+    entry.sa.len = length;
+    entry.sa.a = *scriptanalysis;
+    add_call(sequences, ANALYZER_ID, &entry);
+    return S_OK;
+}
+
+static HRESULT WINAPI analysissink_SetLineBreakpoints(IDWriteTextAnalysisSink *iface,
+        UINT32 position,
+        UINT32 length,
+        DWRITE_LINE_BREAKPOINT const* breakpoints)
+{
+    ok(0, "unexpected\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI analysissink_SetBidiLevel(IDWriteTextAnalysisSink *iface,
+        UINT32 position,
+        UINT32 length,
+        UINT8 explicitLevel,
+        UINT8 resolvedLevel)
+{
+    ok(0, "unexpected\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI analysissink_SetNumberSubstitution(IDWriteTextAnalysisSink *iface,
+        UINT32 position,
+        UINT32 length,
+        IDWriteNumberSubstitution* substitution)
+{
+    ok(0, "unexpected\n");
+    return E_NOTIMPL;
+}
+
+static IDWriteTextAnalysisSinkVtbl analysissinkvtbl = {
+    analysissink_QueryInterface,
+    analysissink_AddRef,
+    analysissink_Release,
+    analysissink_SetScriptAnalysis,
+    analysissink_SetLineBreakpoints,
+    analysissink_SetBidiLevel,
+    analysissink_SetNumberSubstitution
+};
+
+static IDWriteTextAnalysisSink analysissink = { &analysissinkvtbl };
+
+static HRESULT WINAPI analysissource_QueryInterface(IDWriteTextAnalysisSource *iface,
+    REFIID riid, void **obj)
+{
+    ok(0, "QueryInterface not expected\n");
+    return E_NOTIMPL;
+}
+
+static ULONG WINAPI analysissource_AddRef(IDWriteTextAnalysisSource *iface)
+{
+    ok(0, "AddRef not expected\n");
+    return 2;
+}
+
+static ULONG WINAPI analysissource_Release(IDWriteTextAnalysisSource *iface)
+{
+    ok(0, "Release not expected\n");
+    return 1;
+}
+
+static const WCHAR *g_source;
+
+static HRESULT WINAPI analysissource_GetTextAtPosition(IDWriteTextAnalysisSource *iface,
+    UINT32 position, WCHAR const** text, UINT32* text_len)
+{
+    if (position >= lstrlenW(g_source))
+    {
+        *text = NULL;
+        *text_len = 0;
+    }
+    else
+    {
+        *text = &g_source[position];
+        *text_len = lstrlenW(g_source) - position;
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI analysissource_GetTextBeforePosition(IDWriteTextAnalysisSource *iface,
+    UINT32 position, WCHAR const** text, UINT32* text_len)
+{
+    ok(0, "unexpected\n");
+    return E_NOTIMPL;
+}
+
+static DWRITE_READING_DIRECTION WINAPI analysissource_GetParagraphReadingDirection(
+    IDWriteTextAnalysisSource *iface)
+{
+    ok(0, "unexpected\n");
+    return DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
+}
+
+static HRESULT WINAPI analysissource_GetLocaleName(IDWriteTextAnalysisSource *iface,
+    UINT32 position, UINT32* text_len, WCHAR const** locale)
+{
+    *locale = NULL;
+    *text_len = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI analysissource_GetNumberSubstitution(IDWriteTextAnalysisSource *iface,
+    UINT32 position, UINT32* text_len, IDWriteNumberSubstitution **substitution)
+{
+    ok(0, "unexpected\n");
+    return E_NOTIMPL;
+}
+
+static IDWriteTextAnalysisSourceVtbl analysissourcevtbl = {
+    analysissource_QueryInterface,
+    analysissource_AddRef,
+    analysissource_Release,
+    analysissource_GetTextAtPosition,
+    analysissource_GetTextBeforePosition,
+    analysissource_GetParagraphReadingDirection,
+    analysissource_GetLocaleName,
+    analysissource_GetNumberSubstitution
+};
+
+static IDWriteTextAnalysisSource analysissource = { &analysissourcevtbl };
+
+struct sa_test {
+    const WCHAR string[20];
+    int item_count;
+    struct script_analysis sa[10];
+};
+
+static struct sa_test sa_tests[] = {
+    {
+      {'t', 'e', 's', 't',0}, 1,
+      { { 0, 4, { 38, DWRITE_SCRIPT_SHAPES_DEFAULT } }} },
+    { {0} }
+};
+
+static void init_expected_sa(struct call_sequence **seq, const struct sa_test *test)
+{
+    static const struct call_entry end_of_sequence = { LastKind };
+    int i;
+
+    flush_sequence(seq, 0);
+
+    /* add expected calls */
+    for (i = 0; i < test->item_count; i++)
+    {
+        struct call_entry call;
+
+        call.kind = ScriptAnalysis;
+        call.sa.pos = test->sa[i].pos;
+        call.sa.len = test->sa[i].len;
+        call.sa.a = test->sa[i].a;
+        add_call(seq, 0, &call);
+    }
+
+    /* and stop marker */
+    add_call(seq, 0, &end_of_sequence);  
+}
+
+static void test_AnalyzeScript(void)
+{
+    const struct sa_test *ptr = sa_tests;
+    IDWriteTextAnalyzer *analyzer;
+    HRESULT hr;
+
+    hr = IDWriteFactory_CreateTextAnalyzer(factory, &analyzer);
+todo_wine
+    ok(hr == S_OK, "got 0x%08x\n", hr);;
+    if (hr != S_OK) return;
+
+    while (*ptr->string)
+    {
+        g_source = ptr->string;
+
+        init_expected_sa(expected_seq, ptr);
+        hr = IDWriteTextAnalyzer_AnalyzeScript(analyzer, &analysissource, 0, lstrlenW(g_source), &analysissink);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        ok_sequence(sequences, ANALYZER_ID, expected_seq[0]->sequence, "AnalyzeScript", FALSE);
+        ptr++;
+    }
+
+    IDWriteTextAnalyzer_Release(analyzer);
+}
+
+START_TEST(analyzer)
+{
+    HRESULT hr;
+
+    hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, &IID_IDWriteFactory, (IUnknown**)&factory);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    if (hr != S_OK)
+    {
+        win_skip("failed to create factory\n");
+        return;
+    }
+
+    init_call_sequences(sequences, NUM_CALL_SEQUENCES);
+    init_call_sequences(expected_seq, 1);
+
+    test_AnalyzeScript();
+
+    IDWriteFactory_Release(factory);
+}
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index dde50eb..9138061 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -21,8 +21,6 @@
 #define COBJMACROS
 
 #include "windows.h"
-
-#include "initguid.h"
 #include "dwrite.h"
 
 #include "wine/test.h"
-- 
1.7.10.4




More information about the wine-patches mailing list