1 : // Copyright 2012 Google Inc.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/common/application.h"
16 :
17 : #include <shellapi.h>
18 :
19 : #include "base/file_util.h"
20 : #include "gmock/gmock.h"
21 : #include "gtest/gtest.h"
22 : #include "syzygy/common/unittest_util.h"
23 :
24 : namespace common {
25 :
26 : using ::testing::Return;
27 : using ::testing::ScopedLogLevelSaver;
28 : using ::testing::StrictMock;
29 : using ::testing::_;
30 :
31 : namespace {
32 :
33 : const char kTestAppImplName[] = "Test Application (Unit Test)";
34 :
35 : // A test application that simply makes the AppImplBase concrete.
36 : class TestAppImpl : public AppImplBase {
37 : public:
38 E : TestAppImpl() : AppImplBase(kTestAppImplName) {
39 E : }
40 : };
41 :
42 : // A mock application implementation class
43 : class MockAppImpl : public AppImplBase {
44 : public:
45 E : MockAppImpl() : AppImplBase("Mock Application (Unit Test)") {
46 E : }
47 :
48 E : MOCK_METHOD1(ParseCommandLine, bool(const CommandLine*));
49 E : MOCK_METHOD0(SetUp, bool());
50 E : MOCK_METHOD0(Run, int());
51 E : MOCK_METHOD0(TearDown, bool());
52 : };
53 :
54 : // Handy types we'll use below.
55 : typedef Application<TestAppImpl, INIT_LOGGING_YES> TestApp;
56 : typedef Application<StrictMock<MockAppImpl>, INIT_LOGGING_NO> MockApp;
57 :
58 : // A basic test fixture that sets up dummy standard streams.
59 : class ApplicationTest : public testing::ApplicationTestBase {
60 : protected:
61 E : ApplicationTest() : cmd_line_(FilePath(L"test.exe")) {
62 E : }
63 :
64 : template<typename App>
65 E : void RerouteAppStreams(App* app) {
66 E : ASSERT_TRUE(app != NULL);
67 :
68 : // Validate that app's streams were initialized properly.
69 E : ASSERT_EQ(stdin, app->in());
70 E : ASSERT_EQ(stdout, app->out());
71 E : ASSERT_EQ(stderr, app->err());
72 :
73 : // Route test_app_ streams to
74 E : app->set_in(in());
75 E : app->set_out(out());
76 E : app->set_err(err());
77 :
78 E : ASSERT_EQ(in(), app->in());
79 E : ASSERT_EQ(out(), app->out());
80 E : ASSERT_EQ(err(), app->err());
81 E : }
82 :
83 E : virtual void SetUp() OVERRIDE {
84 E : testing::Test::SetUp();
85 :
86 : // Validate test streams were created.
87 E : ASSERT_TRUE(in() != NULL);
88 E : ASSERT_TRUE(out() != NULL);
89 E : ASSERT_TRUE(err() != NULL);
90 :
91 : // Reroute the test application streams.
92 E : RerouteAppStreams(&test_app_);
93 E : RerouteAppStreams(&mock_app_);
94 E : }
95 :
96 : CommandLine cmd_line_;
97 : TestApp test_app_;
98 : MockApp mock_app_;
99 : };
100 :
101 : } // namespace
102 :
103 E : TEST_F(ApplicationTest, AppImplBaseDefault) {
104 : // The command line for this process has already been set we can pass
105 : // whatever we want to Main and it will end up using the the current
106 : // command line.
107 E : const CommandLine* current_command_line = CommandLine::ForCurrentProcess();
108 E : ASSERT_TRUE(current_command_line != NULL);
109 :
110 : // Validate the application name.
111 E : EXPECT_EQ(kTestAppImplName, test_app_.name());
112 :
113 : // Check the default command line and streams.
114 E : EXPECT_EQ(current_command_line, test_app_.command_line());
115 :
116 : // Validate the accessors.
117 E : test_app_.set_command_line(&cmd_line_);
118 E : EXPECT_EQ(&cmd_line_, test_app_.command_line());
119 :
120 E : EXPECT_EQ(0, test_app_.Run());
121 E : }
122 :
123 E : TEST_F(ApplicationTest, AppImplBaseVerbosity) {
124 E : ScopedLogLevelSaver log_level_saver;
125 :
126 E : cmd_line_.AppendSwitchASCII("verbose", "2");
127 E : test_app_.set_command_line(&cmd_line_);
128 :
129 E : ASSERT_EQ(0, test_app_.Run());
130 E : ASSERT_EQ(-2, logging::GetMinLogLevel());
131 E : }
132 :
133 E : TEST_F(ApplicationTest, MockAppFailsCommandLineParsing) {
134 E : MockAppImpl& mock_impl = mock_app_.implementation();
135 :
136 : EXPECT_CALL(mock_impl, ParseCommandLine(_))
137 E : .WillOnce(Return(false));
138 E : EXPECT_NE(0, mock_app_.Run());
139 E : }
140 :
141 E : TEST_F(ApplicationTest, MockAppFailsSetup) {
142 E : MockAppImpl& mock_impl = mock_app_.implementation();
143 :
144 : EXPECT_CALL(mock_impl, ParseCommandLine(_))
145 E : .WillOnce(Return(true));
146 : EXPECT_CALL(mock_impl, SetUp())
147 E : .WillOnce(Return(false));
148 E : EXPECT_NE(0, mock_app_.Run());
149 E : }
150 :
151 E : TEST_F(ApplicationTest, MockAppFailsRun) {
152 E : MockAppImpl& mock_impl = mock_app_.implementation();
153 :
154 : EXPECT_CALL(mock_impl, ParseCommandLine(_))
155 E : .WillOnce(Return(true));
156 : EXPECT_CALL(mock_impl, SetUp())
157 E : .WillOnce(Return(true));
158 : EXPECT_CALL(mock_impl, Run())
159 E : .WillOnce(Return(2));
160 E : EXPECT_CALL(mock_impl, TearDown());
161 E : EXPECT_EQ(2, mock_app_.Run());
162 E : }
163 :
164 E : TEST_F(ApplicationTest, AbsolutePath) {
165 E : AppImplBase& app_impl = test_app_.implementation();
166 E : FilePath current_dir;
167 E : ASSERT_TRUE(file_util::GetCurrentDirectory(¤t_dir));
168 :
169 E : const FilePath kRelativePath(L"foo\\bar\\file.txt");
170 E : const FilePath kAbsolutePath(current_dir.Append(kRelativePath));
171 :
172 E : EXPECT_EQ(FilePath(), app_impl.AbsolutePath(FilePath()));
173 E : EXPECT_EQ(kAbsolutePath, app_impl.AbsolutePath(kRelativePath));
174 E : EXPECT_EQ(kAbsolutePath, app_impl.AbsolutePath(kAbsolutePath));
175 E : }
176 :
177 : } // namespace common
|