1 /*-
2  * Copyright (c) 2010, 2020 Oracle and/or its affiliates.  All rights reserved.
3  *
4  * See the file LICENSE for license information.
5  *
6  */
7 
8 package repmgrtests;
9 
10 import org.junit.Test;
11 import static org.junit.Assert.*;
12 
13 import java.io.File;
14 
15 /**
16  * Test of Replication Manager's ability to discriminate between
17  * per-connection wire protocol versions.  When configured to use
18  * heartbeats, a modern repmgr nevertheless should ignore them when
19  * talking to a v1 connection.
20  */
21 // TODO: it might make more sense to refer to sites with a name, which
22 // could double as the env directory name.
23 //
24 public class TestMixedHeartbeats extends AbstractUpgTest {
25 
26     public interface Ops {
setConfig(Config c)27         public void setConfig(Config c);
joinExistingClient(int site, boolean useHB)28         public void joinExistingClient(int site, boolean useHB)
29             throws Exception;
becomeMaster(int site)30         public void becomeMaster(int site) throws Exception;
getStats(int site)31         public MyStats getStats(int site) throws Exception;
checkMinVersion()32         public void checkMinVersion() throws Exception;
checkpoint(int site)33         public void checkpoint(int site) throws Exception;
34     }
35 
36     public interface Ops46 {
setConfig(Config c)37         public void setConfig(Config c);
createMaster(int site, boolean configureClient)38         public void createMaster(int site, boolean configureClient)
39             throws Exception;
establishClient(int site, boolean configureMaster)40         public void establishClient(int site, boolean configureMaster)
41             throws Exception;
shutDown(int siteId)42         public void shutDown(int siteId) throws Exception;
remove(int site)43         public void remove(int site) throws Exception;
checkMaxVersion()44         public void checkMaxVersion() throws Exception;
45     }
46 
47 
TestMixedHeartbeats()48     public TestMixedHeartbeats() {
49         super("46", "repmgrtests.V46impl", "repmgrtests.CurrentImpl");
50     }
51 
upg()52     @Test public void upg() throws Exception {
53         Ops46 oldGroup = (Ops46)oldGroup_o;
54         Ops currentGroup = (Ops)currentGroup_o;
55 
56         // also: ask DB its version, and make sure it's what we expect
57         // (or at least in reasonable range),
58         // otherwise we have no business running this test.
59 
60         // create a v1 master, maybe add some data
61         // create a v2 client to join (configured for hb), wait for start-up done
62         // maybe write some new txns at master, see that they get to client
63         // pause for hb monitor time expiration
64         // verify that no election has been called (check election stats at each site, I guess)
65         // shut down v1 master
66         // verify that client site takes over (use nsites == 2, and don't disable kluge)
67         // upgrade site 1, and have it rejoin as a client
68         // pause again, verify no add'l election (not counting the one take-over we know about)
69         // (maybe we don't need fiddler, since we've already tested normal v2 hb operation)
70         //
71         // V1 operations:
72         //    create master
73         //    write some txns
74         //    read some stats
75         //    shut down, recover, remove (for upgrade)
76         // v2 operations:
77         //    join a group, wait for start-up done
78         //    read some stats
79         //    run a checkpoint
80         //
81         // version-independent configuration:
82         //    master port 6000
83         //    client port 6001
84         //    base directory (site directories to be generated by some simple rule?)
85 
86         File testdir = new File("TESTDIR");
87         Util.rm_rf(testdir);
88         testdir.mkdir();
89         Config config = new Config(testdir);
90         oldGroup.setConfig(config);
91         currentGroup.setConfig(config);
92 
93         oldGroup.createMaster(0, false);
94         oldGroup.establishClient(1, true);
95 
96         currentGroup.joinExistingClient(1, true);
97 
98         // Even though the v1 site clearly cannot be sending heartbeats,
99         // the v2 site should be smart enough not to consider that an
100         // error, even though it is configured for heartbeats.
101         //
102         MyStats s1 = currentGroup.getStats(1);
103         long initialCount = s1.elections;
104         long initialEgen = s1.egen;
105         Thread.sleep(10000);
106         s1 = currentGroup.getStats(1);
107         assertEquals(initialCount, s1.elections);
108         assertEquals(initialEgen, s1.egen);
109 
110         // Shut down master, verify that client takes over.
111         //
112         oldGroup.shutDown(0);
113         currentGroup.becomeMaster(1);
114         s1 = currentGroup.getStats(1);
115         assertEquals(initialCount+1, s1.elections);
116         assertTrue("Site 1 is now master", s1.envId == s1.master);
117 
118         // Upgrade the former master (site 0), and rejoin the group.
119         // NB: IINM, this form of upgrade works when the log formats may have
120         // changed, but database formats have not.  I guess if a
121         // future release changes database formats, we'll have to go
122         // through a bit more work to do this upgrade in the test here.
123         //
124         oldGroup.remove(0);
125         currentGroup.checkpoint(0);
126         currentGroup.joinExistingClient(0, true);
127 
128         // Now site 1 is master, and site 0 has rejoined as a client, both running
129         // 4.7 (or higher).  Pause again; heartbeats should be flowing, and there
130         // should be no interruption for elections.
131         //
132         MyStats s0 = currentGroup.getStats(0);
133         assertTrue(s0.envId != s0.master);
134         s1 = currentGroup.getStats(1);
135         assertTrue(s1.envId == s1.master);
136         initialCount = s0.elections;
137         initialEgen = s0.egen;
138         Thread.sleep(10000);
139         s0 = currentGroup.getStats(0);
140         assertEquals(initialCount, s0.elections);
141         assertEquals(initialEgen, s0.egen);
142     }
143 
144     // TODO: during mixed mode, write some txns at master to verify that
145     // acks can be transmitted correctly.  (Shall we check that the master
146     // really does recognize that it has a site connected?)
147 }
148