/*
 * Copyright 2025 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "tests/Test.h"

#if defined(SK_GRAPHITE)

#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkString.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/PrecompileContext.h"
#include "include/gpu/graphite/Surface.h"
#include "include/gpu/graphite/precompile/PaintOptions.h"
#include "include/gpu/graphite/precompile/Precompile.h"
#include "include/gpu/graphite/precompile/PrecompileBlender.h"
#include "include/gpu/graphite/precompile/PrecompileColorFilter.h"
#include "include/gpu/graphite/precompile/PrecompileRuntimeEffect.h"
#include "include/gpu/graphite/precompile/PrecompileShader.h"
#include "src/core/SkRuntimeEffectPriv.h"
#include "src/gpu/graphite/ContextPriv.h"
#include "src/gpu/graphite/PrecompileContextPriv.h"
#include "src/gpu/graphite/ShaderCodeDictionary.h"
#include "tools/graphite/ContextFactory.h"
#include "tools/graphite/GraphiteToolUtils.h"
#include "tools/graphite/PipelineCallbackHandler.h"
#include "tools/graphite/UniqueKeyUtils.h"
#include "tools/graphite/precompile/PrecompileEffectFactories.h"

extern bool gGraphiteAvoidDepth;

using namespace::skgpu::graphite;
using namespace skiatest::graphite;
using namespace skiatools::graphite;

namespace {

std::pair<SkPaint, PaintOptions> create_paint_and_options(bool addBlenders) {
    SkPaint paint;
    PaintOptions paintOptions;

    auto [shader, shaderOption] = PrecompileFactories::CreateAnnulusRuntimeShader();

    paint.setShader(std::move(shader));
    paintOptions.setShaders({{ std::move(shaderOption) }});

    auto [colorFilter, colorFilterOption] = PrecompileFactories::CreateComboRuntimeColorFilter();

    paint.setColorFilter(std::move(colorFilter));
    paintOptions.setColorFilters({{ std::move(colorFilterOption) }});

    if (addBlenders) {
        auto [blender, blenderOption] = PrecompileFactories::CreateComboRuntimeBlender();

        paint.setBlender(std::move(blender));
        paintOptions.setBlenders({{ std::move(blenderOption) }});
    }

    return { paint, paintOptions };
}

bool draw_with_normal_api(skgpu::graphite::Context* context,
                          skgpu::graphite::Recorder* recorder,
                          const SkPaint& paint) {
    auto ii = SkImageInfo::Make({ 256, 256 }, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder, ii, skgpu::Mipmapped::kNo);
    if (!surface) {
        return false;
    }

    SkCanvas* canvas = surface->getCanvas();

    canvas->drawRect({0, 0, 100, 100}, paint);

    std::unique_ptr<skgpu::graphite::Recording> recording = recorder->snap();
    if (!recording) {
        return false;
    }

    if (!context->insertRecording({ recording.get() })) {
        return false;
    }

    if (!context->submit(skgpu::graphite::SyncToCpu::kYes)) {
        return false;
    }

    return true;
}

void fetch_keys_and_reset(skiatest::Reporter* reporter,
                          PipelineCallBackHandler* handler,
                          PrecompileContext* precompileContext,
                          std::vector<skgpu::UniqueKey>* uniqueKeys,
                          std::vector<sk_sp<SkData>>* serializedKeys,
                          bool reset) {
    UniqueKeyUtils::FetchUniqueKeys(precompileContext, uniqueKeys);
    handler->retrieveKeys(serializedKeys);

    if (reset) {
        GlobalCache* globalCache = precompileContext->priv().globalCache();

        globalCache->resetGraphicsPipelines();
        REPORTER_ASSERT(reporter, globalCache->numGraphicsPipelines() == 0);
        handler->reset();
    }
}

// Get the existing keys, reset, and try recreating them all w/ the serialized pipeline keys
void reset_and_recreate_pipelines_with_serialized_keys(
            skiatest::Reporter* reporter,
            Context* context,
            Recorder* recorder,
            PrecompileContext* precompileContext,
            PipelineCallBackHandler* handler) {
    GlobalCache* globalCache = precompileContext->priv().globalCache();
    ShaderCodeDictionary* shaderCodeDictionary = context->priv().shaderCodeDictionary();

    auto [paint, _] = create_paint_and_options(/* addBlenders= */ true);

    draw_with_normal_api(context, recorder, paint);

    // None of the user-defined stable runtime effects should've been transmuted to not-stable
    REPORTER_ASSERT(reporter, !shaderCodeDictionary->numUserDefinedRuntimeEffects());

    std::vector<skgpu::UniqueKey> origKeys;
    std::vector<sk_sp<SkData>> androidStyleKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &origKeys, &androidStyleKeys, /* reset= */ true);

    // Given 'draw_with_normal_api' we expect one serialized key - full of user-defined stable keys
    REPORTER_ASSERT(reporter, origKeys.size() == 1);
    REPORTER_ASSERT(reporter, androidStyleKeys.size() == 1);

    // Use the serialized keys to regenerate the Pipelines
    for (sk_sp<SkData>& d : androidStyleKeys) {
        bool result = precompileContext->precompile(d);
        SkAssertResult(result);
    }

    // We need to explicitly wait for the precompilation to finish here
    context->priv().sharedContext()->pipelineManager()->wait_TestOnly();

    // None of the user-defined stable runtime effects should've been transmuted to not-stable
    REPORTER_ASSERT(reporter, !shaderCodeDictionary->numUserDefinedRuntimeEffects());

    std::vector<skgpu::UniqueKey> recreatedKeys;
    std::vector<sk_sp<SkData>> recreatedAndroidStyleKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &recreatedKeys, &recreatedAndroidStyleKeys, /* reset= */ false);

    REPORTER_ASSERT(reporter, recreatedKeys.size() == 1);
    REPORTER_ASSERT(reporter, origKeys[0] == recreatedKeys[0]);

    REPORTER_ASSERT(reporter, recreatedAndroidStyleKeys.size() == 1);
    REPORTER_ASSERT(reporter, androidStyleKeys[0]->equals(recreatedAndroidStyleKeys[0].get()));

    int numBeforeSecondDraw = globalCache->numGraphicsPipelines();

    draw_with_normal_api(context, recorder, paint);

    // None of the user-defined stable runtime effects should've been transmuted to not-stable
    REPORTER_ASSERT(reporter, !shaderCodeDictionary->numUserDefinedRuntimeEffects());

    // Re-drawing shouldn't create any new pipelines
    REPORTER_ASSERT(reporter, numBeforeSecondDraw == globalCache->numGraphicsPipelines(),
                    "%d != %d", numBeforeSecondDraw, globalCache->numGraphicsPipelines());
}

// Get the existing keys, reset, and then try recreating them all using the normal precompile API
void reset_and_recreate_pipelines_with_normal_precompile_api(
            skiatest::Reporter* reporter,
            Context* context,
            Recorder* recorder,
            PrecompileContext* precompileContext,
            PipelineCallBackHandler* handler) {
    // We don't attach runtime blenders to the SkPaint and PaintOptions in this case bc that will
    // force a dest read and complicate the normal-pipeline/Precompile-pipeline
    // comparison on Native Mac and Vulkan. This is bc, for those platforms, Precompile skips some
    // LoadOp combinations which don't matter for those platforms (please see 'numLoadOps' in
    // Precompile) but are serialized (for simplicity) in the serialized pipeline keys.
    auto [paint, paintOptions] = create_paint_and_options(/* addBlenders= */ false);

    draw_with_normal_api(context, recorder, paint);

    std::vector<skgpu::UniqueKey> origKeys;
    std::vector<sk_sp<SkData>> androidStyleKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &origKeys, &androidStyleKeys, /* reset= */ true);

    // Given 'draw_with_normal_api' we expect one serialized key - full of user-defined stable keys
    REPORTER_ASSERT(reporter, origKeys.size() == 1);
    REPORTER_ASSERT(reporter, androidStyleKeys.size() == 1);

    RenderPassProperties renderPassProps;
    renderPassProps.fDSFlags = gGraphiteAvoidDepth ? DepthStencilFlags::kNone : DepthStencilFlags::kDepth;

    Precompile(precompileContext,
               paintOptions,
               DrawTypeFlags::kSimpleShape,
               {{ renderPassProps }});

    // We need to explicitly wait for the precompilation to finish here
    context->priv().sharedContext()->pipelineManager()->wait_TestOnly();

    std::vector<skgpu::UniqueKey> recreatedKeys;
    std::vector<sk_sp<SkData>> recreatedAndroidStyleKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &recreatedKeys, &recreatedAndroidStyleKeys, /* reset= */ true);

    // The normal precompile API will overgenerate, so we need to search for a match
    {
        bool foundIt = false;
        for (const skgpu::UniqueKey& k : recreatedKeys) {
            if (origKeys[0] == k) {
                foundIt = true;
                break;
            }
        }
        REPORTER_ASSERT(reporter, foundIt);
    }
    {
        bool foundIt = false;
        for (const sk_sp<SkData>& k : recreatedAndroidStyleKeys) {
            if (androidStyleKeys[0]->equals(k.get())) {
                foundIt = true;
                break;
            }
        }
        REPORTER_ASSERT(reporter, foundIt);
    }
}

// This helper creates a defective user-defined known runtime effect pair:
//     the blessed shader will have a user-defined stable key
//     the cursed shader has the same SkSL as the blessed one but no stable key
std::pair<sk_sp<SkShader>, sk_sp<SkShader>> make_defective_annulus_shader_pair() {
    SkRuntimeEffect* blessed = PrecompileFactories::GetAnnulusShaderEffect();

    sk_sp<SkRuntimeEffect> cursed(SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader,
                                                      PrecompileFactories::GetAnnulusShaderCode()));

    SkASSERT(blessed != cursed.get());

    static const float kUniforms[4] = { 50.0f, 50.0f, 40.0f, 50.0f };

    sk_sp<SkData> uniforms = SkData::MakeWithCopy(kUniforms, sizeof(kUniforms));

    return { blessed->makeShader(uniforms, /* children= */ {}),
             cursed->makeShader(uniforms, /* children= */ {}) };
}

// Draw once with a registered runtime effect, reset, and then re-draw w/ an un-registered
// runtime effect that uses the same SkSL.
void test_sksl_reuse(skiatest::Reporter* reporter,
                     Context* context,
                     Recorder* recorder,
                     PrecompileContext* precompileContext,
                     PipelineCallBackHandler* handler) {
    auto [blessedShader, cursedShader] = make_defective_annulus_shader_pair();

    SkASSERT(blessedShader != cursedShader);

    // The blessed paint is the static one from the PrecompileFactories which has been
    // registered as a user-defined known runtime effect.
    SkPaint blessedPaint;
    blessedPaint.setShader(std::move(blessedShader));

    // The cursed paint uses the same SkSL as the blessed version but uses a wholly separate
    // runtime effect (which is not registered).
    SkPaint cursedPaint;
    cursedPaint.setShader(std::move(cursedShader));

    draw_with_normal_api(context, recorder, blessedPaint);

    std::vector<skgpu::UniqueKey> origKeys;
    std::vector<sk_sp<SkData>> serializedKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &origKeys, &serializedKeys, /* reset= */ true);

    // Given 'draw_with_normal_api' we expect one serialized key - full of user-defined stable keys
    REPORTER_ASSERT(reporter, origKeys.size() == 1);
    REPORTER_ASSERT(reporter, serializedKeys.size() == 1);

    draw_with_normal_api(context, recorder, cursedPaint);

    std::vector<skgpu::UniqueKey> recreatedKeys;
    std::vector<sk_sp<SkData>> recreatedSerializedKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &recreatedKeys, &recreatedSerializedKeys, /* reset= */ true);

    REPORTER_ASSERT(reporter, recreatedKeys.size() == 1);
    REPORTER_ASSERT(reporter, origKeys[0] == recreatedKeys[0]);

    // The un-registered runtime effect should've been mapped back to the registered one
    // and successfully serialized.
    REPORTER_ASSERT(reporter, recreatedSerializedKeys.size() == 1);
    REPORTER_ASSERT(reporter, serializedKeys[0]->equals(recreatedSerializedKeys[0].get()));
}

void test_get_pipeline_label_api(skiatest::Reporter* reporter,
                                 Context* context,
                                 Recorder* recorder,
                                 PrecompileContext* precompileContext,
                                 PipelineCallBackHandler* handler) {
    auto [paint, paintOptions] = create_paint_and_options(/* addBlenders= */ true);

    draw_with_normal_api(context, recorder, paint);

    std::vector<skgpu::UniqueKey> origKeys;
    std::vector<sk_sp<SkData>> androidStyleKeys;

    fetch_keys_and_reset(reporter, handler, precompileContext,
                         &origKeys, &androidStyleKeys, /* reset= */ true);

    // Given 'draw_with_normal_api' we expect one serialized key - full of user-defined stable keys
    REPORTER_ASSERT(reporter, origKeys.size() == 1);
    REPORTER_ASSERT(reporter, androidStyleKeys.size() == 1);

    std::string label = precompileContext->getPipelineLabel(androidStyleKeys[0]);

    REPORTER_ASSERT(reporter, std::string::npos != label.find("AnnulusShader"));
    REPORTER_ASSERT(reporter, std::string::npos != label.find("SrcBlender"));
    REPORTER_ASSERT(reporter, std::string::npos != label.find("DstBlender"));
    REPORTER_ASSERT(reporter, std::string::npos != label.find("ComboBlender"));
    REPORTER_ASSERT(reporter, std::string::npos != label.find("DoubleColorFilter"));
    REPORTER_ASSERT(reporter, std::string::npos != label.find("ComboColorFilter"));
    // We withheld the HalfColorFilter name to test the default name case
    REPORTER_ASSERT(reporter, std::string::npos == label.find("HalfColorFilter"));
    REPORTER_ASSERT(reporter, std::string::npos != label.find("UserDefinedKnownRuntimeEffect"));
}


} // anonymous namespace

// This test adds some user-defined stably-keyed runtime effects and then verifies that
// everything behaves as expected. For the purposes of this test, "behaves as expected" means:
//    1) the user-defined stably keyed runtime effects appear as such in the ShaderCodeDictionary
//    2) the user-defined stable keys appear in the serialized Pipeline
//       keys (i.e., from the PipelineCallBackHandler)
//    3) said keys correctly (re)generate the desired pipelines
//    4) the normal (non-serialized-key) Precompile API generates the same keys.
//    5) if the blessed stable runtime-effects aren't used, the free-range runtime-effects are
//       mapped back to the stable runtime-effects (clients really shouldn't do this though!)
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(UserDefinedStableKeyTest,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           origContext,
                                           origTestContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {
    auto pipelineHandler = std::make_unique<PipelineCallBackHandler>();

    TestOptions newOptions(origOptions);
    newOptions.fContextOptions.fPipelineCallbackContext = pipelineHandler.get();
    newOptions.fContextOptions.fPipelineCachingCallback = PipelineCallBackHandler::CallBack;

    // We're going to also use all these runtime effects via the normal API
    // (c.f. create_paint_and_options)
    static const int kNumUserDefinedStableKeys = 7;
    sk_sp<SkRuntimeEffect> userDefinedKnownRuntimeEffects[kNumUserDefinedStableKeys] = {
        sk_ref_sp(PrecompileFactories::GetAnnulusShaderEffect()),

        sk_ref_sp(PrecompileFactories::GetSrcBlenderEffect()),
        sk_ref_sp(PrecompileFactories::GetDstBlenderEffect()),
        sk_ref_sp(PrecompileFactories::GetComboBlenderEffect()),

        sk_ref_sp(PrecompileFactories::GetDoubleColorFilterEffect()),
        sk_ref_sp(PrecompileFactories::GetHalfColorFilterEffect()),
        sk_ref_sp(PrecompileFactories::GetComboColorFilterEffect()),
    };

    for (const sk_sp<SkRuntimeEffect>& e: userDefinedKnownRuntimeEffects) {
        // The PrecompileFactories runtime effects are static so prior runs may have already
        // set their StableKeys. Reset the StableKeys so all our expectations/asserts will be met.
        SkRuntimeEffectPriv::ResetStableKey(e.get());
    }

    newOptions.fContextOptions.fUserDefinedKnownRuntimeEffects = { userDefinedKnownRuntimeEffects };

    ContextFactory workaroundFactory(newOptions);
    ContextInfo ctxInfo = workaroundFactory.getContextInfo(origTestContext->contextType());

    Context* newContext = ctxInfo.fContext;
    std::unique_ptr<PrecompileContext> precompileContext = newContext->makePrecompileContext();
    GlobalCache* globalCache = precompileContext->priv().globalCache();
    ShaderCodeDictionary* shaderCodeDictionary = newContext->priv().shaderCodeDictionary();
    std::unique_ptr<Recorder> recorder =
            newContext->makeRecorder(ToolUtils::CreateTestingRecorderOptions());

    REPORTER_ASSERT(reporter, !globalCache->numGraphicsPipelines());
    // The next two lines check #1 above
    REPORTER_ASSERT(reporter, !shaderCodeDictionary->numUserDefinedRuntimeEffects());
    REPORTER_ASSERT(reporter, shaderCodeDictionary->numUserDefinedKnownRuntimeEffects() ==
                              kNumUserDefinedStableKeys);

    // This verifies #2 and #3 above
    reset_and_recreate_pipelines_with_serialized_keys(reporter,
                                                      newContext,
                                                      recorder.get(),
                                                      precompileContext.get(),
                                                      pipelineHandler.get());

    globalCache->resetGraphicsPipelines();
    pipelineHandler->reset();

    // This tests out #4 above
    reset_and_recreate_pipelines_with_normal_precompile_api(reporter,
                                                            newContext,
                                                            recorder.get(),
                                                            precompileContext.get(),
                                                            pipelineHandler.get());

    globalCache->resetGraphicsPipelines();
    pipelineHandler->reset();

    // This tests out #5 above
    test_sksl_reuse(reporter,
                    newContext,
                    recorder.get(),
                    precompileContext.get(),
                    pipelineHandler.get());

    globalCache->resetGraphicsPipelines();
    pipelineHandler->reset();

    // Extra little test to check on the getPipelineLabel API
    test_get_pipeline_label_api(reporter,
                                newContext,
                                recorder.get(),
                                precompileContext.get(),
                                pipelineHandler.get());
}

// Test that the ShaderCodeDictionary can deduplicate the user-defined known runtime effect list
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(UserDefinedStableKeyTest_Duplicates,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           testContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {

    auto pipelineHandler = std::make_unique<PipelineCallBackHandler>();

    TestOptions newOptions(origOptions);
    newOptions.fContextOptions.fPipelineCallbackContext = pipelineHandler.get();
    newOptions.fContextOptions.fPipelineCachingCallback = PipelineCallBackHandler::CallBack;

    sk_sp<SkRuntimeEffect> userDefinedKnownRuntimeEffects[] = {
            sk_ref_sp(PrecompileFactories::GetAnnulusShaderEffect()),
            sk_ref_sp(PrecompileFactories::GetAnnulusShaderEffect()),
    };

    for (const sk_sp<SkRuntimeEffect>& e: userDefinedKnownRuntimeEffects) {
        // The PrecompileFactories runtime effects are static so prior runs may have already
        // set their StableKeys. Reset the StableKeys so all our expectations/asserts will be met.
        SkRuntimeEffectPriv::ResetStableKey(e.get());
    }

    newOptions.fContextOptions.fUserDefinedKnownRuntimeEffects = { userDefinedKnownRuntimeEffects };

    ContextFactory workaroundFactory(newOptions);
    ContextInfo ctxInfo = workaroundFactory.getContextInfo(testContext->contextType());

    ShaderCodeDictionary* shaderCodeDictionary = ctxInfo.fContext->priv().shaderCodeDictionary();

    REPORTER_ASSERT(reporter, shaderCodeDictionary->numUserDefinedKnownRuntimeEffects() == 1);
}

// Test that the ShaderCodeDictionary can handle nullptrs in the
// user-defined known runtime effect list
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(UserDefinedStableKeyTest_Nullptrs,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           testContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {

    auto pipelineHandler = std::make_unique<PipelineCallBackHandler>();

    TestOptions newOptions(origOptions);
    newOptions.fContextOptions.fPipelineCallbackContext = pipelineHandler.get();
    newOptions.fContextOptions.fPipelineCachingCallback = PipelineCallBackHandler::CallBack;

    sk_sp<SkRuntimeEffect> userDefinedKnownRuntimeEffects[] = {
            sk_ref_sp(PrecompileFactories::GetAnnulusShaderEffect()),
            nullptr,
            sk_ref_sp(PrecompileFactories::GetSrcBlenderEffect()),
    };

    for (const sk_sp<SkRuntimeEffect>& e : userDefinedKnownRuntimeEffects) {
        // The PrecompileFactories runtime effects are static so prior runs may have already
        // set their StableKeys. Reset the StableKeys so all our expectations/asserts will be met.
        if (e) {
            SkRuntimeEffectPriv::ResetStableKey(e.get());
        }
    }

    newOptions.fContextOptions.fUserDefinedKnownRuntimeEffects = { userDefinedKnownRuntimeEffects };

    ContextFactory workaroundFactory(newOptions);
    ContextInfo ctxInfo = workaroundFactory.getContextInfo(testContext->contextType());

    ShaderCodeDictionary* shaderCodeDictionary = ctxInfo.fContext->priv().shaderCodeDictionary();

    REPORTER_ASSERT(reporter, shaderCodeDictionary->numUserDefinedKnownRuntimeEffects() == 2);
}

// Test that the ShaderCodeDictionary can handle excess user-defined known runtime effects
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(UserDefinedStableKeyTest_Overflow,
                                           skgpu::IsRenderingContext,
                                           reporter,
                                           context,
                                           testContext,
                                           origOptions,
                                           /* optionsProc= */ nullptr,
                                           /* condition= */ true,
                                           CtsEnforcement::kNever) {

    auto pipelineHandler = std::make_unique<PipelineCallBackHandler>();

    TestOptions newOptions(origOptions);
    newOptions.fContextOptions.fPipelineCallbackContext = pipelineHandler.get();
    newOptions.fContextOptions.fPipelineCachingCallback = PipelineCallBackHandler::CallBack;

    std::vector<sk_sp<SkRuntimeEffect>> userDefinedKnownRuntimeEffects;

    for (int i = 0; i < 2*SkKnownRuntimeEffects::kUserDefinedKnownRuntimeEffectsReservedCnt; ++i) {
        SkString sksl;
        sksl.printf("half4 main(float2 xy) { return half4(%d/255.0, %d/255.0, %d/255.0, 1.0); }",
                    i, i, i);
        userDefinedKnownRuntimeEffects.push_back(SkRuntimeEffect::MakeForShader(sksl).effect);
    }

    newOptions.fContextOptions.fUserDefinedKnownRuntimeEffects = { userDefinedKnownRuntimeEffects };

    ContextFactory workaroundFactory(newOptions);
    ContextInfo ctxInfo = workaroundFactory.getContextInfo(testContext->contextType());

    ShaderCodeDictionary* shaderCodeDictionary = ctxInfo.fContext->priv().shaderCodeDictionary();

    REPORTER_ASSERT(reporter, shaderCodeDictionary->numUserDefinedKnownRuntimeEffects() ==
                              SkKnownRuntimeEffects::kUserDefinedKnownRuntimeEffectsReservedCnt);
}

#endif // SK_GRAPHITE
