| Index: remoting/client/chromoting_view_unittest.cc
|
| ===================================================================
|
| --- remoting/client/chromoting_view_unittest.cc (revision 0)
|
| +++ remoting/client/chromoting_view_unittest.cc (revision 0)
|
| @@ -0,0 +1,558 @@
|
| +// Copyright (c) 2010 The Chromium 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 "base/scoped_ptr.h"
|
| +#include "remoting/base/protocol/chromotocol.pb.h"
|
| +#include "remoting/client/chromoting_view.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::InSequence;
|
| +using ::testing::Return;
|
| +
|
| +namespace remoting {
|
| +
|
| +class MockDecoder : public Decoder {
|
| + public:
|
| + MockDecoder() {}
|
| +
|
| + MOCK_METHOD4(BeginDecode, bool(scoped_refptr<media::VideoFrame> frame,
|
| + UpdatedRects* updated_rects,
|
| + Task* partial_decode_done,
|
| + Task* decode_done));
|
| + MOCK_METHOD1(PartialDecode, bool(HostMessage* message));
|
| + MOCK_METHOD0(EndDecode, void());
|
| +
|
| + MOCK_METHOD0(Encoding, UpdateStreamEncoding());
|
| + MOCK_METHOD0(IsStarted, bool());
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(MockDecoder);
|
| +};
|
| +
|
| +// Fake ChromotingView that provides stub implementations for all pure virtual
|
| +// methods. This is sufficient since we're only interested in testing the
|
| +// base class methods in this file.
|
| +class FakeView : public ChromotingView {
|
| + bool Initialize() { return false; }
|
| + void TearDown() {}
|
| + void Paint() {}
|
| + void SetSolidFill(uint32 color) {}
|
| + void UnsetSolidFill() {}
|
| + void SetViewport(int x, int y, int width, int height) {
|
| + frame_width_ = width;
|
| + frame_height_ = height;
|
| + }
|
| + void SetHostScreenSize(int width, int height) {}
|
| + void HandleBeginUpdateStream(HostMessage* msg) {}
|
| + void HandleUpdateStreamPacket(HostMessage* msg) {}
|
| + void HandleEndUpdateStream(HostMessage* msg) {}
|
| +
|
| + public:
|
| + // Testing accessors.
|
| + // These provide access to private/protected members of ChromotingView so
|
| + // that they can be tested/verified.
|
| + Decoder* get_decoder() {
|
| + return decoder_.get();
|
| + }
|
| + void set_decoder(Decoder* decoder) {
|
| + decoder_.reset(decoder);
|
| + }
|
| +
|
| + // Testing wrappers for private setup/startup decoder routines.
|
| + bool setup_decoder(UpdateStreamEncoding encoding) {
|
| + return SetupDecoder(encoding);
|
| + }
|
| + bool begin_decoding(Task* partial_decode_done, Task* decode_done) {
|
| + return BeginDecoding(partial_decode_done, decode_done);
|
| + }
|
| + bool decode(HostMessage* msg) {
|
| + return Decode(msg);
|
| + }
|
| + bool end_decoding() {
|
| + return EndDecoding();
|
| + }
|
| +
|
| + // Testing setup.
|
| + void set_test_viewport() {
|
| + SetViewport(0, 0, 640, 480);
|
| + }
|
| +};
|
| +
|
| +// Verify the initial state.
|
| +TEST(ChromotingViewTest, InitialState) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + EXPECT_TRUE(view->get_decoder() == NULL);
|
| +}
|
| +
|
| +// Test a simple decoder sequence:
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket:
|
| +// SetupDecoder - return false
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleEndUpdateStream:
|
| +// EndDecoding
|
| +TEST(ChromotingViewTest, DecodeSimple) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + view->set_test_viewport();
|
| +
|
| + // HandleBeginUpdateStream
|
| +
|
| + // HandleUpdateStreamPacket
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + Decoder* decoder = view->get_decoder();
|
| + ASSERT_TRUE(decoder != NULL);
|
| + EXPECT_EQ(EncodingZlib, decoder->Encoding());
|
| + EXPECT_EQ(false, decoder->IsStarted());
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder = new MockDecoder();
|
| + view->set_decoder(mock_decoder);
|
| + EXPECT_CALL(*mock_decoder, Encoding())
|
| + .WillRepeatedly(Return(EncodingZlib));
|
| + {
|
| + InSequence s;
|
| +
|
| + // BeginDecoding
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*mock_decoder, BeginDecode(_, _, _, _))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(true));
|
| +
|
| + // Decode
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder, PartialDecode(_))
|
| + .WillOnce(Return(true));
|
| +
|
| + // EndDecoding
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder, EndDecode())
|
| + .Times(1);
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false));
|
| + }
|
| +
|
| + // decoder_->IsStarted() is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleEndUpdateStream
|
| +
|
| + ASSERT_TRUE(view->end_decoding());
|
| +}
|
| +
|
| +// Test a three-packet decoder sequence:
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket: (1)
|
| +// SetupDecoder - return false
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleUpdateStreamPacket: (2)
|
| +// SetupDecoder - return true
|
| +// Decode
|
| +// HandleUpdateStreamPacket: (3)
|
| +// SetupDecoder - return true
|
| +// Decode
|
| +// HandleEndUpdateStream:
|
| +// EndDecoding
|
| +TEST(ChromotingViewTest, DecodeThreePackets) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + view->set_test_viewport();
|
| +
|
| + // HandleBeginUpdateStream
|
| +
|
| + // HandleUpdateStreamPacket (1)
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + Decoder* decoder = view->get_decoder();
|
| + ASSERT_TRUE(decoder != NULL);
|
| + EXPECT_EQ(EncodingZlib, decoder->Encoding());
|
| + EXPECT_EQ(false, decoder->IsStarted());
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder = new MockDecoder();
|
| + view->set_decoder(mock_decoder);
|
| + EXPECT_CALL(*mock_decoder, Encoding())
|
| + .WillRepeatedly(Return(EncodingZlib));
|
| + EXPECT_CALL(*mock_decoder, BeginDecode(_, _, _, _))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder, PartialDecode(_))
|
| + .Times(3)
|
| + .WillRepeatedly(Return(true));
|
| + EXPECT_CALL(*mock_decoder, EndDecode())
|
| + .Times(1);
|
| + {
|
| + InSequence s;
|
| +
|
| + // BeginDecoding
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + // BeginDecoding (1)
|
| + // Decode (1)
|
| + // SetupDecoder (1)
|
| + // Decode (1)
|
| + // SetupDecoder (1)
|
| + // Decode (1)
|
| + // EndDecoding (1)
|
| + // Total = 7 calls
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .Times(7)
|
| + .WillRepeatedly(Return(true))
|
| + .RetiresOnSaturation();
|
| + // EndDecoding
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + }
|
| +
|
| + // decoder_->IsStarted() is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleUpdateStreamPacket (2)
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + // Don't call BeginDecoding() because it is already started.
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleUpdateStreamPacket (3)
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + // Don't call BeginDecoding() because it is already started.
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleEndUpdateStream
|
| +
|
| + ASSERT_TRUE(view->end_decoding());
|
| +}
|
| +
|
| +// Test two update streams: (same packet encoding)
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket:
|
| +// SetupDecoder - return false
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleEndUpdateStream:
|
| +// EndDecoding
|
| +//
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket:
|
| +// SetupDecoder - return false
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleEndUpdateStream:
|
| +// EndDecoding
|
| +TEST(ChromotingViewTest, DecodeTwoStreams) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + view->set_test_viewport();
|
| +
|
| + // HandleBeginUpdateStream (update stream 1)
|
| +
|
| + // HandleUpdateStreamPacket
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + Decoder* decoder = view->get_decoder();
|
| + ASSERT_TRUE(decoder != NULL);
|
| + EXPECT_EQ(EncodingZlib, decoder->Encoding());
|
| + EXPECT_EQ(false, decoder->IsStarted());
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder = new MockDecoder();
|
| + view->set_decoder(mock_decoder);
|
| + EXPECT_CALL(*mock_decoder, Encoding())
|
| + .WillRepeatedly(Return(EncodingZlib));
|
| + EXPECT_CALL(*mock_decoder, BeginDecode(_, _, _, _))
|
| + .Times(2)
|
| + .WillRepeatedly(Return(true));
|
| + EXPECT_CALL(*mock_decoder, PartialDecode(_))
|
| + .Times(2)
|
| + .WillRepeatedly(Return(true));
|
| + EXPECT_CALL(*mock_decoder, EndDecode())
|
| + .Times(2);
|
| + {
|
| + InSequence s;
|
| + // BeginDecoding
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + // BeginDecoding (1)
|
| + // Decode (1)
|
| + // EndDecoding (1)
|
| + // Total = 3 calls
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .Times(3)
|
| + .WillRepeatedly(Return(true))
|
| + .RetiresOnSaturation();
|
| + // EndDecoding (1)
|
| + // SetupDecoder (1)
|
| + // BeginDecoding (1)
|
| + // Total = 3 calls
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .Times(3)
|
| + .WillRepeatedly(Return(false))
|
| + .RetiresOnSaturation();
|
| + // BeginDecoding (1)
|
| + // Decode (1)
|
| + // EndDecoding (1)
|
| + // Total = 3 calls
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .Times(3)
|
| + .WillRepeatedly(Return(true))
|
| + .RetiresOnSaturation();
|
| + // EndDecoding
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + }
|
| +
|
| + // |started| is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleEndUpdateStream
|
| +
|
| + ASSERT_TRUE(view->end_decoding());
|
| +
|
| + // HandleBeginUpdateStream (update stream 2)
|
| +
|
| + // HandleUpdateStreamPacket
|
| +
|
| + Decoder* old_decoder = view->get_decoder();
|
| + view->setup_decoder(EncodingZlib);
|
| + // Verify we're using the same decoder since the encoding matches.
|
| + Decoder* new_decoder = view->get_decoder();
|
| + ASSERT_TRUE(new_decoder == old_decoder);
|
| +
|
| + // |started| is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleEndUpdateStream
|
| +
|
| + ASSERT_TRUE(view->end_decoding());
|
| +}
|
| +
|
| +// Test two update streams with different encodings:
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket: ('Zlib' encoded)
|
| +// SetupDecoder
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleEndUpdateStream:
|
| +// EndDecoding
|
| +//
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket: ('None' encoded)
|
| +// SetupDecoder
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleEndUpdateStream:
|
| +// EndDecoding
|
| +TEST(ChromotingViewTest, DecodeTwoStreamsDifferentEncodings) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + view->set_test_viewport();
|
| +
|
| + // HandleBeginUpdateStream (update stream 1)
|
| +
|
| + // HandleUpdateStreamPacket
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + Decoder* decoder = view->get_decoder();
|
| + ASSERT_TRUE(decoder != NULL);
|
| + EXPECT_EQ(EncodingZlib, decoder->Encoding());
|
| + EXPECT_EQ(false, decoder->IsStarted());
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder1 = new MockDecoder();
|
| + view->set_decoder(mock_decoder1);
|
| + EXPECT_CALL(*mock_decoder1, Encoding())
|
| + .WillRepeatedly(Return(EncodingZlib));
|
| + EXPECT_CALL(*mock_decoder1, BeginDecode(_, _, _, _))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder1, PartialDecode(_))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder1, EndDecode());
|
| + {
|
| + InSequence s1;
|
| + // BeginDecoding
|
| + EXPECT_CALL(*mock_decoder1, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + // BeginDecoding (1)
|
| + // Decode (1)
|
| + // EndDecoding (1)
|
| + // Total = 3 calls
|
| + EXPECT_CALL(*mock_decoder1, IsStarted())
|
| + .Times(3)
|
| + .WillRepeatedly(Return(true))
|
| + .RetiresOnSaturation();
|
| + // EndDecoding (1)
|
| + // SetupDecoder (1)
|
| + // Total = 2 calls
|
| + EXPECT_CALL(*mock_decoder1, IsStarted())
|
| + .Times(2)
|
| + .WillRepeatedly(Return(false))
|
| + .RetiresOnSaturation();
|
| + }
|
| +
|
| + // |started| is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleEndUpdateStream
|
| +
|
| + ASSERT_TRUE(view->end_decoding());
|
| +
|
| + // HandleBeginUpdateStream (update stream 2)
|
| +
|
| + // HandleUpdateStreamPacket
|
| +
|
| + // Encoding for second stream is different from first, so this will
|
| + // create a new decoder.
|
| + ASSERT_TRUE(view->setup_decoder(EncodingNone));
|
| + // The decoder should be new.
|
| + EXPECT_NE(mock_decoder1, view->get_decoder());
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder2 = new MockDecoder();
|
| + view->set_decoder(mock_decoder2);
|
| + EXPECT_CALL(*mock_decoder2, Encoding())
|
| + .WillRepeatedly(Return(EncodingNone));
|
| + EXPECT_CALL(*mock_decoder2, BeginDecode(_, _, _, _))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder2, PartialDecode(_))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder2, EndDecode());
|
| + {
|
| + InSequence s2;
|
| + // BeginDecoding
|
| + EXPECT_CALL(*mock_decoder2, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + // BeginDecoding (1)
|
| + // Decode (1)
|
| + // EndDecoding (1)
|
| + // Total = 3 calls
|
| + EXPECT_CALL(*mock_decoder2, IsStarted())
|
| + .Times(3)
|
| + .WillRepeatedly(Return(true))
|
| + .RetiresOnSaturation();
|
| + // EndDecoding
|
| + EXPECT_CALL(*mock_decoder2, IsStarted())
|
| + .WillOnce(Return(false))
|
| + .RetiresOnSaturation();
|
| + }
|
| +
|
| + // |started| is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleEndUpdateStream
|
| +
|
| + ASSERT_TRUE(view->end_decoding());
|
| +}
|
| +
|
| +// Test failure when packets in a stream have mismatched encodings.
|
| +// HandleBeginUpdateStream:
|
| +// HandleUpdateStreamPacket: (1)
|
| +// SetupDecoder - encoding = Zlib
|
| +// BeginDecoding
|
| +// Decode
|
| +// HandleUpdateStreamPacket: (2)
|
| +// SetupDecoder - encoding = none
|
| +// DEATH
|
| +TEST(ChromotingViewTest, MismatchedEncodings) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + view->set_test_viewport();
|
| +
|
| + // HandleBeginUpdateStream
|
| +
|
| + // HandleUpdateStreamPacket (1)
|
| + // encoding = Zlib
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + Decoder* decoder = view->get_decoder();
|
| + ASSERT_TRUE(decoder != NULL);
|
| + EXPECT_EQ(EncodingZlib, decoder->Encoding());
|
| + EXPECT_EQ(false, decoder->IsStarted());
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder = new MockDecoder();
|
| + view->set_decoder(mock_decoder);
|
| + EXPECT_CALL(*mock_decoder, Encoding())
|
| + .WillRepeatedly(Return(EncodingZlib));
|
| + {
|
| + InSequence s;
|
| +
|
| + // BeginDecoding().
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false));
|
| + EXPECT_CALL(*mock_decoder, BeginDecode(_, _, _, _))
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(true));
|
| +
|
| + // Decode().
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(*mock_decoder, PartialDecode(_))
|
| + .WillOnce(Return(true));
|
| +
|
| + // SetupDecoder().
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(true));
|
| + }
|
| +
|
| + // |started| is false, so we call begin_decoding().
|
| + ASSERT_TRUE(view->begin_decoding(NULL, NULL));
|
| +
|
| + ASSERT_TRUE(view->decode(NULL));
|
| +
|
| + // HandleUpdateStreamPacket (2)
|
| + // encoding = None
|
| +
|
| + // Doesn't match previous packet encoding, so returns failure.
|
| + ASSERT_FALSE(view->setup_decoder(EncodingNone));
|
| +}
|
| +
|
| +// Verify we fail when Decode() is called without first calling
|
| +// BeginDecoding().
|
| +TEST(ChromotingViewTest, MissingBegin) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + view->set_test_viewport();
|
| +
|
| + ASSERT_TRUE(view->setup_decoder(EncodingZlib));
|
| + ASSERT_TRUE(view->get_decoder() != NULL);
|
| +
|
| + // Overwrite |decoder_| with MockDecoder.
|
| + MockDecoder* mock_decoder = new MockDecoder();
|
| + view->set_decoder(mock_decoder);
|
| + EXPECT_CALL(*mock_decoder, IsStarted())
|
| + .WillOnce(Return(false));
|
| +
|
| + // Call decode() without calling begin_decoding().
|
| + EXPECT_FALSE(view->decode(NULL));
|
| +}
|
| +
|
| +// Test requesting a decoder for an invalid encoding.
|
| +TEST(ChromotingViewTest, InvalidEncoding) {
|
| + scoped_ptr<FakeView> view(new FakeView());
|
| + EXPECT_FALSE(view->setup_decoder(EncodingInvalid));
|
| +}
|
| +
|
| +} // namespace remoting
|
|
|
| Property changes on: remoting/client/chromoting_view_unittest.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|