/*

 * Copyright (C) 2024 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



#include "gtest/gtest.h"

#include "filter/filter.h"

#include "subtitle_sink.h"

#include "sink/media_synchronous_sink.h"



using namespace testing::ext;



namespace OHOS {

namespace Media {

namespace Test {

using namespace Pipeline;



class TestEventReceiver : public EventReceiver {

public:

    explicit TestEventReceiver()

    {

    }



    void OnEvent(const Event &event)

    {

        (void)event;

    }



private:

};



std::shared_ptr<SubtitleSink> SubtitleSinkCreate()

{

    auto sink = std::make_shared<SubtitleSink>();

    auto meta = std::make_shared<Meta>();

    std::shared_ptr<EventReceiver> testEventReceiver = std::make_shared<TestEventReceiver>();

    sink->Init(meta, testEventReceiver);

    sink->SetParameter(meta);

    sink->GetParameter(meta);

    sink->SetIsTransitent(false);

    sink->SetEventReceiver(testEventReceiver);

    sink->DrainOutputBuffer(false);

    sink->ResetSyncInfo();

    return sink;

}



HWTEST(TestSubtitleSink, do_sync_write_not_eos, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->PrepareInputBufferQueue();

    sink->Prepare();

    sink->state_ = Pipeline::FilterState::READY;

    auto bufferQP = sink->GetBufferQueueProducer();

    ASSERT_TRUE(bufferQP != nullptr);

    auto bufferQC = sink->GetBufferQueueConsumer();

    ASSERT_TRUE(bufferQC != nullptr);

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    sink->isThreadExit_ = true;

    sink->RenderLoop();

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    std::shared_ptr<AVBuffer> buffer = nullptr;

    auto ret = bufferQP->RequestBuffer(buffer, config, 1000);

    ASSERT_TRUE(ret == Status::OK);

    ASSERT_TRUE(buffer != nullptr && buffer->memory_ != nullptr);

    auto addr = buffer->memory_->GetAddr();

    char subtitle[] = "test";

    memcpy_s(addr, 4, subtitle, 4);

    ret = bufferQP->ReturnBuffer(buffer, true);

}

 

HWTEST(TestSubtitleSink, do_sync_write_two_frames_case1, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    SubtitleSink::SubtitleInfo tempSubtitleInfo = {"test", 1, 1};

    sink->NotifyRender(tempSubtitleInfo);

    sink->isThreadExit_ = true;

    sink->CalcWaitTime(tempSubtitleInfo);

    sink->ActionToDo(tempSubtitleInfo);

    sink->RenderLoop();

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_prepare_two_frames_case2, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->PrepareInputBufferQueue();

    sink->PrepareInputBufferQueue();

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    sink->shouldUpdate_ = true;

    SubtitleSink::SubtitleInfo tempSubtitleInfo = {"test", 1, 1};

    std::shared_ptr<EventReceiver> testEventReceiver = std::make_shared<TestEventReceiver>();

    sink->SetEventReceiver(testEventReceiver);

    sink->NotifyRender(tempSubtitleInfo);

    sink->isThreadExit_ = true;

    sink->RenderLoop();

    sink->isEos_ = false;

    sink->filledOutputBuffer_ = std::make_shared<AVBuffer>();

    sink->filledOutputBuffer_->flag_ = 1;

    sink->filledOutputBuffer_->memory_= std::make_shared<AVMemory>();

    sink->DrainOutputBuffer(true);

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_prepare_two_frames_case3, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->PrepareInputBufferQueue();

    sink->PrepareInputBufferQueue();

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    sink->isThreadExit_ = true;

    sink->shouldUpdate_ = false;

    sink->RenderLoop();

    sink->filledOutputBuffer_ = std::make_shared<AVBuffer>();

    sink->filledOutputBuffer_->flag_ = 1;

    sink->filledOutputBuffer_->memory_= std::make_shared<AVMemory>();

    sink->DrainOutputBuffer(true);

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_prepare_two_frames_case4, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->PrepareInputBufferQueue();

    sink->PrepareInputBufferQueue();

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    sink->isThreadExit_ = true;

    sink->RenderLoop();

    sink->filledOutputBuffer_ = std::make_shared<AVBuffer>();

    sink->filledOutputBuffer_->flag_ = 1;

    sink->filledOutputBuffer_->memory_= std::make_shared<AVMemory>();

    sink->DrainOutputBuffer(true);

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_prepare_two_frames_case5, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->PrepareInputBufferQueue();

    sink->PrepareInputBufferQueue();

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    sink->subtitleInfoVec_.push_back({"test", 2, 1});

    sink->isThreadExit_ = true;

    sink->RenderLoop();

    sink->filledOutputBuffer_ = std::make_shared<AVBuffer>();

    sink->filledOutputBuffer_->flag_ = 1;

    sink->filledOutputBuffer_->memory_= std::make_shared<AVMemory>();

    sink->DrainOutputBuffer(true);

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_prepare_two_frames_case6, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->PrepareInputBufferQueue();

    sink->PrepareInputBufferQueue();

    sink->Prepare();

    sink->isThreadExit_ = true;

    sink->RenderLoop();

    sink->filledOutputBuffer_ = std::make_shared<AVBuffer>();

    sink->filledOutputBuffer_->flag_ = 1;

    sink->filledOutputBuffer_->memory_= std::make_shared<AVMemory>();

    sink->DrainOutputBuffer(true);

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_two_frames_case7, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    SubtitleSink::SubtitleInfo tempSubtitleInfo = {"test", 1, 1};

    sink->NotifyRender(tempSubtitleInfo);

    sink->isThreadExit_ = true;

    sink->CalcWaitTime(tempSubtitleInfo);

    sink->ActionToDo(tempSubtitleInfo);

    sink->RenderLoop();

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_two_frames_case8, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    sink->Prepare();

    sink->subtitleInfoVec_.push_back({"test", 1, 1});

    SubtitleSink::SubtitleInfo tempSubtitleInfo = {"test", 2, 2};

    sink->NotifyRender(tempSubtitleInfo);

 

    sink->CalcWaitTime(tempSubtitleInfo);

    sink->ActionToDo(tempSubtitleInfo);

    sink->isThreadExit_ = true;

    sink->RenderLoop();

 

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    const std::shared_ptr<AVBuffer> buffer2 = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 0; // not eos

    sink->DoSyncWrite(buffer2, actionClock);

    sink->SetSpeed(2.0F);

    sink->Flush(true);

    sink->Pause();

    sink->NotifySeek();

    sink->Resume();

    sink->Stop();

    sink->Release();

    EXPECT_EQ(sink->Release(), Status::OK);

}

 

HWTEST(TestSubtitleSink, do_sync_write_eos, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    auto syncCenter = std::make_shared<MediaSyncManager>();

    sink->SetSyncCenter(syncCenter);

    AVBufferConfig config;

    config.size = 4;

    config.memoryType = MemoryType::SHARED_MEMORY;

    const std::shared_ptr<AVBuffer> buffer = AVBuffer::CreateAVBuffer(config);

    buffer->flag_ = 1; // eos

    int64_t actionClock = 0;

    sink->DoSyncWrite(buffer, actionClock);

    sink->DoSyncWrite(buffer, actionClock);

    buffer->flag_ = BUFFER_FLAG_EOS;

    sink->DoSyncWrite(buffer, actionClock);

    ASSERT_TRUE(sink->DoSyncWrite(buffer, actionClock) != -1);

}



HWTEST(TestSubtitleSink, GetTargetSubtitleIndex, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    ASSERT_TRUE(sink != nullptr);

    sink->GetTargetSubtitleIndex(0);

    EXPECT_EQ(sink->currentInfoIndex_, 0);

}



HWTEST(TestSubtitleSink, GetBufferQueue, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    sink->state_ = Pipeline::FilterState::INITIALIZED;

    EXPECT_EQ(sink->GetBufferQueueProducer(), nullptr);

    EXPECT_EQ(sink->GetBufferQueueConsumer(), nullptr);

}



HWTEST(TestSubtitleSink, createSink, TestSize.Level1)

{

    auto sink = std::make_shared<SubtitleSink>();

    std::shared_ptr<Meta> meta = nullptr;

    std::shared_ptr<EventReceiver> testEventReceiver = std::make_shared<TestEventReceiver>();

    EXPECT_EQ(sink->Init(meta, testEventReceiver), Status::OK);

}

HWTEST(TestSubtitleSink, RemoveTextTags_001, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test1 = "<b>bold</b> text";

    EXPECT_EQ(sink->RemoveTextTags(test1), "bold text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_002, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test2 = "<i>italic</i> text";

    EXPECT_EQ(sink->RemoveTextTags(test2), "italic text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_003, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test3 = "<gggg>text</gggg>";

    EXPECT_EQ(sink->RemoveTextTags(test3), "text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_004, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test4 = "</i> closing without opening";

    EXPECT_EQ(sink->RemoveTextTags(test4), "</i> closing without opening");

}



HWTEST(TestSubtitleSink, RemoveTextTags_005, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test5 = "<b>unclosed bold";

    EXPECT_EQ(sink->RemoveTextTags(test5), "unclosed bold");

}



HWTEST(TestSubtitleSink, RemoveTextTags_006, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test6 = "<gggg>unclosed unsupported";

    EXPECT_EQ(sink->RemoveTextTags(test6), "<gggg>unclosed unsupported");

}



HWTEST(TestSubtitleSink, RemoveTextTags_007, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test7 = "<b><i>bold italic</i></b>";

    EXPECT_EQ(sink->RemoveTextTags(test7), "bold italic");

}



HWTEST(TestSubtitleSink, RemoveTextTags_008, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test8 = "text <i>italic</i> more text";

    EXPECT_EQ(sink->RemoveTextTags(test8), "text italic more text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_009, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test9 = "<font color='red'>colored</font> text";

    EXPECT_EQ(sink->RemoveTextTags(test9), "colored text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_010, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test10 = "<font>al7<font color=\"#ff0000\">English:When</font></font>";

    EXPECT_EQ(sink->RemoveTextTags(test10), "al7English:When");

}



HWTEST(TestSubtitleSink, RemoveTextTags_011, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test11 = "<font color='red'><i>colored</font></i> text";

    EXPECT_EQ(sink->RemoveTextTags(test11), "colored text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_012, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test12 = "<font color='red'><ggg>colored</font></ggg> text";

    EXPECT_EQ(sink->RemoveTextTags(test12), "colored text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_013, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test13 = "<font color='red'><ggg>colored</font> text";

    EXPECT_EQ(sink->RemoveTextTags(test13), "<ggg>colored text");

}



HWTEST(TestSubtitleSink, RemoveTextTags_014, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test14 = "<b><i></i>";

    EXPECT_EQ(sink->RemoveTextTags(test14), "");

}



HWTEST(TestSubtitleSink, RemoveTextTags_015, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test15 = "a<>a";

    EXPECT_EQ(sink->RemoveTextTags(test15), "a<>a");

}



HWTEST(TestSubtitleSink, RemoveTextTags_016, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test16 = "";

    EXPECT_EQ(sink->RemoveTextTags(test16), "");

}



HWTEST(TestSubtitleSink, RemoveTextTags_017, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test17 = "<b>";

    EXPECT_EQ(sink->RemoveTextTags(test17), "");

}



HWTEST(TestSubtitleSink, RemoveTextTags_018, TestSize.Level1)

{

    auto sink = SubtitleSinkCreate();

    std::string test18 = "<a>";

    EXPECT_EQ(sink->RemoveTextTags(test18), "<a>");

}

}  // namespace Test

}  // namespace Media

}  // namespace OHOS