windowcapture
исходный код / Tip/_selftest.cpp

_selftest.cpp

70 строк · 3,514 байт · модуль Tip
 1// Headless self-test for the TIP — validates the parts that can be checked without a live GUI:
 2//   1) the correction table (confirms the UTF-8 wide literals encoded correctly), and
 3//   2) the full COM lifecycle of WCTip.dll (class factory, instance creation, QueryInterface across
 4//      the multiple-inherited interfaces, and balanced ref-counts) WITHOUT registering the TIP into
 5//      the system input stack. The actual in-place ITfRange edit still needs a live TSF app to test.
 6#include <windows.h>
 7#include <msctf.h>
 8#include <stdio.h>
 9#include "Correct.h"
10
11#include <initguid.h>
12DEFINE_GUID(CLSID_WCTextService, 0x6b2d4f8a, 0x1c3e, 0x4a7b, 0x9f, 0x21, 0x3d, 0x5e, 0x8c, 0x7a, 0x4b, 0x12);
13
14typedef HRESULT (STDAPICALLTYPE *PFN_GCO)(REFCLSID, REFIID, void**);
15typedef HRESULT (STDAPICALLTYPE *PFN_CAN)();
16
17static int g_fail = 0;
18static void check(bool ok, const char* msg) { printf("[%s] %s\n", ok ? "OK  " : "FAIL", msg); if (!ok) g_fail++; }
19
20int main()
21{
22    // 1) brain table — verifies the Cyrillic wide literals survived /utf-8 compilation
23    check(wctip::CorrectWord(L"превет") == L"привет",  "CorrectWord: prevet -> privet");
24    check(wctip::CorrectWord(L"СаБаКа") == L"собака",  "CorrectWord: case-insensitive -> sobaka");
25    check(wctip::CorrectWord(L"малако") == L"молоко",  "CorrectWord: malako -> moloko");
26    check(wctip::CorrectWord(L"привет").empty(),       "CorrectWord: leaves a correct word unchanged");
27    check(wctip::IsSep(L' ') && !wctip::IsSep(L'я'), "IsSep: space yes, letter no");
28
29    // 2) COM lifecycle, no system registration
30    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
31    HMODULE h = LoadLibraryW(L"bin\\WCTip.dll");
32    check(h != NULL, "LoadLibrary bin\\WCTip.dll");
33    if (h)
34    {
35        PFN_GCO pGCO = (PFN_GCO)GetProcAddress(h, "DllGetClassObject");
36        PFN_CAN pCan = (PFN_CAN)GetProcAddress(h, "DllCanUnloadNow");
37        check(pGCO && pCan, "exports DllGetClassObject + DllCanUnloadNow resolved");
38        if (pGCO && pCan)
39        {
40            IClassFactory* pcf = NULL;
41            HRESULT hr = pGCO(CLSID_WCTextService, IID_IClassFactory, (void**)&pcf);
42            check(SUCCEEDED(hr) && pcf, "DllGetClassObject -> IClassFactory");
43            if (pcf)
44            {
45                void* pTip = NULL;
46                hr = pcf->CreateInstance(NULL, IID_ITfTextInputProcessorEx, &pTip);
47                check(SUCCEEDED(hr) && pTip, "CreateInstance -> ITfTextInputProcessorEx");
48                if (pTip)
49                {
50                    ITfTextInputProcessorEx* tip = (ITfTextInputProcessorEx*)pTip;
51                    ITfKeyEventSink* ks = NULL;
52                    hr = tip->QueryInterface(IID_ITfKeyEventSink, (void**)&ks);
53                    check(SUCCEEDED(hr) && ks, "QI -> ITfKeyEventSink (multiple inheritance)");
54                    ITfTextInputProcessor* base = NULL;
55                    hr = tip->QueryInterface(IID_ITfTextInputProcessor, (void**)&base);
56                    check(SUCCEEDED(hr) && base, "QI -> ITfTextInputProcessor");
57                    if (ks) ks->Release();
58                    if (base) base->Release();
59                    tip->Release();
60                }
61                pcf->Release();
62            }
63            check(pCan() == S_OK, "DllCanUnloadNow == S_OK (ref-counts balanced)");
64        }
65        FreeLibrary(h);
66    }
67    CoUninitialize();
68    printf(g_fail == 0 ? "SELFTEST_OK\n" : "SELFTEST_FAILED count=%d\n", g_fail);
69    return g_fail;
70}