1# --
2# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/
3# --
4# This software comes with ABSOLUTELY NO WARRANTY. For details, see
5# the enclosed file COPYING for license information (GPL). If you
6# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt.
7# --
8
9use strict;
10use warnings;
11use utf8;
12
13use vars (qw($Self));
14
15# This test checks the slave handling features in DB.pm
16
17my $MasterDSN      = $Kernel::OM->Get('Kernel::Config')->Get('DatabaseDSN');
18my $MasterUser     = $Kernel::OM->Get('Kernel::Config')->Get('DatabaseUser');
19my $MasterPassword = $Kernel::OM->Get('Kernel::Config')->Get('DatabasePw');
20
21my @Tests = (
22    {
23        Name   => "No slave configured",
24        Config => {
25            'Core::MirrorDB::DSN'               => undef,
26            'Core::MirrorDB::User'              => undef,
27            'Core::MirrorDB::Password'          => undef,
28            'Core::MirrorDB::AdditionalMirrors' => undef,
29        },
30        SlaveDBAvailable => 0,
31        TestIterations   => 1,
32    },
33    {
34        Name   => "First slave configured",
35        Config => {
36            'Core::MirrorDB::DSN'               => $MasterDSN,
37            'Core::MirrorDB::User'              => $MasterUser,
38            'Core::MirrorDB::Password'          => $MasterPassword,
39            'Core::MirrorDB::AdditionalMirrors' => undef,
40        },
41        SlaveDBAvailable => 1,
42        TestIterations   => 1,
43    },
44    {
45        Name   => "First slave configured as invalid",
46        Config => {
47            'Core::MirrorDB::DSN'               => $MasterDSN,
48            'Core::MirrorDB::User'              => 'wrong_user',
49            'Core::MirrorDB::Password'          => 'wrong_password',
50            'Core::MirrorDB::AdditionalMirrors' => undef,
51        },
52        SlaveDBAvailable => 0,
53        TestIterations   => 1,
54    },
55    {
56        Name   => "Additional slave configured",
57        Config => {
58            'Core::MirrorDB::DSN'               => undef,
59            'Core::MirrorDB::User'              => undef,
60            'Core::MirrorDB::Password'          => undef,
61            'Core::MirrorDB::AdditionalMirrors' => {
62                1 => {
63                    DSN      => $MasterDSN,
64                    User     => $MasterUser,
65                    Password => $MasterPassword,
66                },
67            },
68        },
69        SlaveDBAvailable => 1,
70        TestIterations   => 1,
71    },
72    {
73        Name   => "Additional slave configured as invalid",
74        Config => {
75            'Core::MirrorDB::DSN'               => undef,
76            'Core::MirrorDB::User'              => undef,
77            'Core::MirrorDB::Password'          => undef,
78            'Core::MirrorDB::AdditionalMirrors' => {
79                1 => {
80                    DSN      => $MasterDSN,
81                    User     => 'wrong_user',
82                    Password => 'wrong_password',
83                },
84            },
85        },
86        SlaveDBAvailable => 0,
87        TestIterations   => 1,
88    },
89    {
90        Name   => "Full config with valid first slave and invalid additional",
91        Config => {
92            'Core::MirrorDB::DSN'               => $MasterDSN,
93            'Core::MirrorDB::User'              => $MasterUser,
94            'Core::MirrorDB::Password'          => $MasterPassword,
95            'Core::MirrorDB::AdditionalMirrors' => {
96                1 => {
97                    DSN      => $MasterDSN,
98                    User     => 'wrong_user',
99                    Password => 'wrong_password',
100                },
101                2 => {
102                    DSN      => $MasterDSN,
103                    User     => $MasterUser,
104                    Password => $MasterPassword,
105                },
106            },
107        },
108        SlaveDBAvailable => 1,
109
110        # Use many iterations so that also the invalid mirror will be tried first at some point, probably.
111        TestIterations => 10,
112    },
113);
114
115TEST:
116for my $Test (@Tests) {
117
118    for my $TestIteration ( 1 .. $Test->{TestIterations} ) {
119
120        $Kernel::OM->ObjectsDiscard();
121
122        for my $ConfigKey ( sort keys %{ $Test->{Config} } ) {
123            $Kernel::OM->Get('Kernel::Config')->Set(
124                Key   => $ConfigKey,
125                Value => $Test->{Config}->{$ConfigKey},
126            );
127        }
128
129        {
130            # Regular fetch from master
131            my $DBObject = $Kernel::OM->Get('Kernel::System::DB');
132            my @ValidIDs;
133            my $TestPrefix = "$Test->{Name} - $TestIteration - UseSlaveDB 0: ";
134            $DBObject->Prepare(
135                SQL => "\nSELECT id\nFROM valid",    # simulate indentation
136            );
137            while ( my @Row = $DBObject->FetchrowArray() ) {
138                push @ValidIDs, $Row[0];
139            }
140            $Self->True(
141                scalar @ValidIDs,
142                "$TestPrefix valid ids were found",
143            );
144            $Self->True(
145                $DBObject->{Cursor},
146                "$TestPrefix statement handle active on master",
147            );
148            $Self->False(
149                $DBObject->{SlaveDBObject},
150                "$TestPrefix SlaveDB not connected",
151            );
152
153            $Kernel::OM->ObjectsDiscard(
154                Objects => ['Kernel::System::DB'],
155            );
156        }
157
158        {
159            local $Kernel::System::DB::UseSlaveDB = 1;
160
161            my $DBObject   = $Kernel::OM->Get('Kernel::System::DB');
162            my @ValidIDs   = ();
163            my $TestPrefix = "$Test->{Name} - $TestIteration - UseSlaveDB 1: ";
164
165            $DBObject->Prepare(
166                SQL => "\nSELECT id\nFROM valid",    # simulate indentation
167            );
168            while ( my @Row = $DBObject->FetchrowArray() ) {
169                push @ValidIDs, $Row[0];
170            }
171            $Self->True(
172                scalar @ValidIDs,
173                "$TestPrefix valid ids were found",
174            );
175
176            if ( !$Test->{SlaveDBAvailable} ) {
177                $Self->True(
178                    $DBObject->{Cursor},
179                    "$TestPrefix statement handle active on master",
180                );
181                $Self->False(
182                    $DBObject->{SlaveDBObject},
183                    "$TestPrefix SlaveDB not connected",
184                );
185                next TEST;
186            }
187
188            $Self->False(
189                $DBObject->{Cursor},
190                "$TestPrefix statement handle inactive on master",
191            );
192            $Self->True(
193                $DBObject->{SlaveDBObject}->{Cursor},
194                "$TestPrefix statement handle active on slave",
195            );
196
197            $Self->False(
198                scalar $DBObject->Ping( AutoConnect => 0 ),
199                "$TestPrefix master object is not connected automatically",
200            );
201
202            $Self->True(
203                scalar $DBObject->{SlaveDBObject}->Ping( AutoConnect => 0 ),
204                "$TestPrefix slave object is connected",
205            );
206
207            $DBObject->Disconnect();
208
209            $Self->False(
210                scalar $DBObject->Ping( AutoConnect => 0 ),
211                "$TestPrefix master object is disconnected",
212            );
213
214            $Self->False(
215                scalar $DBObject->{SlaveDBObject}->Ping( AutoConnect => 0 ),
216                "$TestPrefix slave object is disconnected",
217            );
218
219            $DBObject->Connect();
220
221            $Self->True(
222                scalar $DBObject->Ping( AutoConnect => 0 ),
223                "$TestPrefix master object is reconnected",
224            );
225
226            $Self->True(
227                scalar $DBObject->{SlaveDBObject}->Ping( AutoConnect => 0 ),
228                "$TestPrefix slave object is not reconnected automatically",
229            );
230        }
231    }
232}
233
2341;
235