Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
StackExchange.Redis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
StackExchange.Redis
Commits
72b1cbab
Commit
72b1cbab
authored
Mar 18, 2018
by
Nick Craver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Tests: add logging for DeslaveGoesToPrimary
...and normalizing line endings because git sucks.
parent
d5027640
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
197 additions
and
194 deletions
+197
-194
MultiMaster.cs
StackExchange.Redis.Tests/MultiMaster.cs
+197
-194
No files found.
StackExchange.Redis.Tests/MultiMaster.cs
View file @
72b1cbab
using
System.Collections.Generic
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.IO
;
using
System.Linq
;
using
System.Linq
;
using
System.Net
;
using
System.Net
;
using
System.Threading.Tasks
;
using
System.Threading.Tasks
;
using
Xunit
;
using
Xunit
;
using
Xunit.Abstractions
;
using
Xunit.Abstractions
;
namespace
StackExchange.Redis.Tests
namespace
StackExchange.Redis.Tests
{
{
[
Collection
(
NonParallelCollection
.
Name
)]
[
Collection
(
NonParallelCollection
.
Name
)]
public
class
MultiMaster
:
TestBase
public
class
MultiMaster
:
TestBase
{
{
protected
override
string
GetConfiguration
()
=>
protected
override
string
GetConfiguration
()
=>
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
+
","
+
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
+
",password="
+
TestConfig
.
Current
.
SecurePassword
;
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
+
","
+
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
+
",password="
+
TestConfig
.
Current
.
SecurePassword
;
public
MultiMaster
(
ITestOutputHelper
output
)
:
base
(
output
)
{
}
public
MultiMaster
(
ITestOutputHelper
output
)
:
base
(
output
)
{
}
[
Fact
]
[
Fact
]
public
void
CannotFlushSlave
()
public
void
CannotFlushSlave
()
{
{
var
ex
=
Assert
.
Throws
<
RedisCommandException
>(()
=>
var
ex
=
Assert
.
Throws
<
RedisCommandException
>(()
=>
{
{
ConfigurationOptions
config
=
GetMasterSlaveConfig
();
ConfigurationOptions
config
=
GetMasterSlaveConfig
();
using
(
var
conn
=
ConnectionMultiplexer
.
Connect
(
config
))
using
(
var
conn
=
ConnectionMultiplexer
.
Connect
(
config
))
{
{
var
servers
=
conn
.
GetEndPoints
().
Select
(
e
=>
conn
.
GetServer
(
e
));
var
servers
=
conn
.
GetEndPoints
().
Select
(
e
=>
conn
.
GetServer
(
e
));
var
slave
=
servers
.
FirstOrDefault
(
x
=>
x
.
IsSlave
);
var
slave
=
servers
.
FirstOrDefault
(
x
=>
x
.
IsSlave
);
Assert
.
NotNull
(
slave
);
// Slave not found, ruh roh
Assert
.
NotNull
(
slave
);
// Slave not found, ruh roh
slave
.
FlushDatabase
();
slave
.
FlushDatabase
();
}
}
});
});
Assert
.
Equal
(
"Command cannot be issued to a slave: FLUSHDB"
,
ex
.
Message
);
Assert
.
Equal
(
"Command cannot be issued to a slave: FLUSHDB"
,
ex
.
Message
);
}
}
[
Fact
]
[
Fact
]
public
async
Task
DeslaveGoesToPrimary
()
public
async
Task
DeslaveGoesToPrimary
()
{
{
ConfigurationOptions
config
=
GetMasterSlaveConfig
();
ConfigurationOptions
config
=
GetMasterSlaveConfig
();
using
(
var
conn
=
ConnectionMultiplexer
.
Connect
(
config
))
using
(
var
conn
=
ConnectionMultiplexer
.
Connect
(
config
))
{
{
var
primary
=
conn
.
GetServer
(
new
IPEndPoint
(
IPAddress
.
Parse
(
TestConfig
.
Current
.
MasterServer
),
TestConfig
.
Current
.
MasterPort
));
var
primary
=
conn
.
GetServer
(
TestConfig
.
Current
.
MasterServer
,
TestConfig
.
Current
.
MasterPort
);
var
secondary
=
conn
.
GetServer
(
new
IPEndPoint
(
IPAddress
.
Parse
(
TestConfig
.
Current
.
SlaveServer
),
TestConfig
.
Current
.
SlavePort
));
var
secondary
=
conn
.
GetServer
(
TestConfig
.
Current
.
SlaveServer
,
TestConfig
.
Current
.
SlavePort
);
primary
.
Ping
();
primary
.
Ping
();
secondary
.
Ping
();
secondary
.
Ping
();
primary
.
MakeMaster
(
ReplicationChangeOptions
.
SetTiebreaker
);
primary
.
MakeMaster
(
ReplicationChangeOptions
.
SetTiebreaker
);
secondary
.
MakeMaster
(
ReplicationChangeOptions
.
None
);
secondary
.
MakeMaster
(
ReplicationChangeOptions
.
None
);
await
Task
.
Delay
(
2000
).
ConfigureAwait
(
false
);
await
Task
.
Delay
(
2000
).
ConfigureAwait
(
false
);
primary
.
Ping
();
primary
.
Ping
();
secondary
.
Ping
();
secondary
.
Ping
();
using
(
var
writer
=
new
StringWriter
())
using
(
var
writer
=
new
StringWriter
())
{
{
conn
.
Configure
(
writer
);
conn
.
Configure
(
writer
);
string
log
=
writer
.
ToString
();
string
log
=
writer
.
ToString
();
Assert
.
True
(
log
.
Contains
(
"tie-break is unanimous at "
+
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
),
"unanimous"
);
Assert
.
True
(
log
.
Contains
(
"tie-break is unanimous at "
+
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
),
"unanimous"
);
}
}
// k, so we know everyone loves 6379; is that what we get?
// k, so we know everyone loves 6379; is that what we get?
var
db
=
conn
.
GetDatabase
();
var
db
=
conn
.
GetDatabase
();
RedisKey
key
=
Me
();
RedisKey
key
=
Me
();
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferMaster
));
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferMaster
));
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandMaster
));
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandMaster
));
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferSlave
));
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferSlave
));
var
ex
=
Assert
.
Throws
<
RedisConnectionException
>(()
=>
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandSlave
));
var
ex
=
Assert
.
Throws
<
RedisConnectionException
>(()
=>
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandSlave
));
Assert
.
StartsWith
(
"No connection is available to service this operation: EXISTS DeslaveGoesToPrimary"
,
ex
.
Message
);
Assert
.
StartsWith
(
"No connection is available to service this operation: EXISTS DeslaveGoesToPrimary"
,
ex
.
Message
);
primary
.
MakeMaster
(
ReplicationChangeOptions
.
Broadcast
|
ReplicationChangeOptions
.
EnslaveSubordinates
|
ReplicationChangeOptions
.
SetTiebreaker
,
Writer
);
primary
.
MakeMaster
(
ReplicationChangeOptions
.
Broadcast
|
ReplicationChangeOptions
.
EnslaveSubordinates
|
ReplicationChangeOptions
.
SetTiebreaker
,
Writer
);
await
Task
.
Delay
(
5000
).
ConfigureAwait
(
false
);
await
Task
.
Delay
(
2000
).
ConfigureAwait
(
false
);
primary
.
Ping
();
primary
.
Ping
();
secondary
.
Ping
();
secondary
.
Ping
();
Assert
.
True
(
primary
.
IsConnected
,
$"
{
primary
.
EndPoint
}
is not connected."
);
Assert
.
True
(
primary
.
IsConnected
,
$"
{
primary
.
EndPoint
}
is not connected."
);
Assert
.
True
(
secondary
.
IsConnected
,
$"
{
secondary
.
EndPoint
}
is not connected."
);
Assert
.
True
(
secondary
.
IsConnected
,
$"
{
secondary
.
EndPoint
}
is not connected."
);
Writer
.
WriteLine
(
$"
{
primary
.
EndPoint
}
:
{
primary
.
ServerType
}
"
);
Writer
.
WriteLine
(
$"
{
primary
.
EndPoint
}
:
{
primary
.
ServerType
}
, Mode:
{(
primary
.
IsSlave
?
"Slave"
:
"Master"
)}
"
);
Writer
.
WriteLine
(
$"
{
secondary
.
EndPoint
}
:
{
secondary
.
ServerType
}
"
);
Writer
.
WriteLine
(
$"
{
secondary
.
EndPoint
}
:
{
secondary
.
ServerType
}
, Mode:
{(
secondary
.
IsSlave
?
"Slave"
:
"Master"
)}
"
);
// Create a separate multiplexer with a valid view of the world to distinguish between failures of
// Create a separate multiplexer with a valid view of the world to distinguish between failures of
// server topology changes from failures to recognize those changes
// server topology changes from failures to recognize those changes
using
(
var
conn2
=
ConnectionMultiplexer
.
Connect
(
config
))
using
(
var
conn2
=
ConnectionMultiplexer
.
Connect
(
config
))
{
{
var
primary2
=
conn
.
GetServer
(
new
IPEndPoint
(
IPAddress
.
Parse
(
TestConfig
.
Current
.
MasterServer
),
TestConfig
.
Current
.
MasterPort
));
var
primary2
=
conn
.
GetServer
(
TestConfig
.
Current
.
MasterServer
,
TestConfig
.
Current
.
MasterPort
);
var
secondary2
=
conn
.
GetServer
(
new
IPEndPoint
(
IPAddress
.
Parse
(
TestConfig
.
Current
.
SlaveServer
),
TestConfig
.
Current
.
SlavePort
));
var
secondary2
=
conn
.
GetServer
(
TestConfig
.
Current
.
SlaveServer
,
TestConfig
.
Current
.
SlavePort
);
Assert
.
False
(
primary2
.
IsSlave
,
$"
{
primary2
.
EndPoint
}
should be a master (verification connection)."
);
Writer
.
WriteLine
(
$"Check:
{
primary2
.
EndPoint
}
:
{
primary2
.
ServerType
}
, Mode:
{(
primary2
.
IsSlave
?
"Slave"
:
"Master"
)}
"
);
Assert
.
True
(
secondary2
.
IsSlave
,
$"
{
secondary2
.
EndPoint
}
should be a slave (verification connection)."
);
Writer
.
WriteLine
(
$"Check:
{
secondary2
.
EndPoint
}
:
{
secondary2
.
ServerType
}
, Mode:
{(
secondary2
.
IsSlave
?
"Slave"
:
"Master"
)}
"
);
var
db2
=
conn
.
GetDatabase
();
Assert
.
False
(
primary2
.
IsSlave
,
$"
{
primary2
.
EndPoint
}
should be a master (verification connection)."
);
Assert
.
True
(
secondary2
.
IsSlave
,
$"
{
secondary2
.
EndPoint
}
should be a slave (verification connection)."
);
Assert
.
Equal
(
primary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferMaster
));
Assert
.
Equal
(
primary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandMaster
));
var
db2
=
conn
.
GetDatabase
();
Assert
.
Equal
(
secondary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferSlave
));
Assert
.
Equal
(
secondary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandSlave
));
Assert
.
Equal
(
primary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferMaster
));
}
Assert
.
Equal
(
primary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandMaster
));
Assert
.
Equal
(
secondary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferSlave
));
Assert
.
False
(
primary
.
IsSlave
,
$"
{
primary
.
EndPoint
}
should be a master."
);
Assert
.
Equal
(
secondary2
.
EndPoint
,
db2
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandSlave
));
Assert
.
True
(
secondary
.
IsSlave
,
$"
{
secondary
.
EndPoint
}
should be a slave."
);
}
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferMaster
));
Assert
.
False
(
primary
.
IsSlave
,
$"
{
primary
.
EndPoint
}
should be a master."
);
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandMaster
));
Assert
.
True
(
secondary
.
IsSlave
,
$"
{
secondary
.
EndPoint
}
should be a slave."
);
Assert
.
Equal
(
secondary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferSlave
));
Assert
.
Equal
(
secondary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandSlave
));
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferMaster
));
}
Assert
.
Equal
(
primary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandMaster
));
}
Assert
.
Equal
(
secondary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
PreferSlave
));
Assert
.
Equal
(
secondary
.
EndPoint
,
db
.
IdentifyEndpoint
(
key
,
CommandFlags
.
DemandSlave
));
private
static
ConfigurationOptions
GetMasterSlaveConfig
()
}
{
}
return
new
ConfigurationOptions
{
private
static
ConfigurationOptions
GetMasterSlaveConfig
()
AllowAdmin
=
true
,
{
SyncTimeout
=
100000
,
return
new
ConfigurationOptions
EndPoints
=
{
{
AllowAdmin
=
true
,
{
TestConfig
.
Current
.
MasterServer
,
TestConfig
.
Current
.
MasterPort
},
SyncTimeout
=
100000
,
{
TestConfig
.
Current
.
SlaveServer
,
TestConfig
.
Current
.
SlavePort
},
EndPoints
=
}
{
};
{
TestConfig
.
Current
.
MasterServer
,
TestConfig
.
Current
.
MasterPort
},
}
{
TestConfig
.
Current
.
SlaveServer
,
TestConfig
.
Current
.
SlavePort
},
}
[
Fact
]
};
public
void
TestMultiNoTieBreak
()
}
{
using
(
var
log
=
new
StringWriter
())
[
Fact
]
using
(
var
conn
=
Create
(
log
:
log
,
tieBreaker
:
""
))
public
void
TestMultiNoTieBreak
()
{
{
Output
.
WriteLine
(
log
.
ToString
());
using
(
var
log
=
new
StringWriter
())
Assert
.
Contains
(
"Choosing master arbitrarily"
,
log
.
ToString
());
using
(
var
conn
=
Create
(
log
:
log
,
tieBreaker
:
""
))
}
{
}
Output
.
WriteLine
(
log
.
ToString
());
Assert
.
Contains
(
"Choosing master arbitrarily"
,
log
.
ToString
());
public
static
IEnumerable
<
object
[
]>
GetConnections
()
}
{
}
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
};
public
static
IEnumerable
<
object
[
]>
GetConnections
()
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
null
};
{
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
null
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
};
yield
return
new
object
[]
{
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
null
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
null
};
yield
return
new
object
[]
{
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
};
yield
return
new
object
[]
{
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
};
yield
return
new
object
[]
{
null
,
null
,
null
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
,
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
};
}
yield
return
new
object
[]
{
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
};
yield
return
new
object
[]
{
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
,
null
,
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
};
[
Theory
,
MemberData
(
nameof
(
GetConnections
))]
yield
return
new
object
[]
{
null
,
null
,
null
};
public
void
TestMultiWithTiebreak
(
string
a
,
string
b
,
string
elected
)
}
{
const
string
TieBreak
=
"__tie__"
;
[
Theory
,
MemberData
(
nameof
(
GetConnections
))]
// set the tie-breakers to the expected state
public
void
TestMultiWithTiebreak
(
string
a
,
string
b
,
string
elected
)
using
(
var
aConn
=
ConnectionMultiplexer
.
Connect
(
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
))
{
{
const
string
TieBreak
=
"__tie__"
;
aConn
.
GetDatabase
().
StringSet
(
TieBreak
,
a
);
// set the tie-breakers to the expected state
}
using
(
var
aConn
=
ConnectionMultiplexer
.
Connect
(
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
MasterPort
))
using
(
var
aConn
=
ConnectionMultiplexer
.
Connect
(
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
+
",password="
+
TestConfig
.
Current
.
SecurePassword
))
{
{
aConn
.
GetDatabase
().
StringSet
(
TieBreak
,
a
);
aConn
.
GetDatabase
().
StringSet
(
TieBreak
,
b
);
}
}
using
(
var
aConn
=
ConnectionMultiplexer
.
Connect
(
TestConfig
.
Current
.
MasterServer
+
":"
+
TestConfig
.
Current
.
SecurePort
+
",password="
+
TestConfig
.
Current
.
SecurePassword
))
{
// see what happens
aConn
.
GetDatabase
().
StringSet
(
TieBreak
,
b
);
using
(
var
log
=
new
StringWriter
())
}
using
(
var
conn
=
Create
(
log
:
log
,
tieBreaker
:
TieBreak
))
{
// see what happens
string
text
=
log
.
ToString
();
using
(
var
log
=
new
StringWriter
())
Output
.
WriteLine
(
text
);
using
(
var
conn
=
Create
(
log
:
log
,
tieBreaker
:
TieBreak
))
Assert
.
False
(
text
.
Contains
(
"failed to nominate"
),
"failed to nominate"
);
{
if
(
elected
!=
null
)
string
text
=
log
.
ToString
();
{
Output
.
WriteLine
(
text
);
Assert
.
True
(
text
.
Contains
(
"Elected: "
+
elected
),
"elected"
);
Assert
.
False
(
text
.
Contains
(
"failed to nominate"
),
"failed to nominate"
);
}
if
(
elected
!=
null
)
int
nullCount
=
(
a
==
null
?
1
:
0
)
+
(
b
==
null
?
1
:
0
);
{
if
((
a
==
b
&&
nullCount
==
0
)
||
nullCount
==
1
)
Assert
.
True
(
text
.
Contains
(
"Elected: "
+
elected
),
"elected"
);
{
}
Assert
.
True
(
text
.
Contains
(
"tie-break is unanimous"
),
"unanimous"
);
int
nullCount
=
(
a
==
null
?
1
:
0
)
+
(
b
==
null
?
1
:
0
);
Assert
.
False
(
text
.
Contains
(
"Choosing master arbitrarily"
),
"arbitrarily"
);
if
((
a
==
b
&&
nullCount
==
0
)
||
nullCount
==
1
)
}
{
else
Assert
.
True
(
text
.
Contains
(
"tie-break is unanimous"
),
"unanimous"
);
{
Assert
.
False
(
text
.
Contains
(
"Choosing master arbitrarily"
),
"arbitrarily"
);
Assert
.
False
(
text
.
Contains
(
"tie-break is unanimous"
),
"unanimous"
);
}
Assert
.
True
(
text
.
Contains
(
"Choosing master arbitrarily"
),
"arbitrarily"
);
else
}
{
}
Assert
.
False
(
text
.
Contains
(
"tie-break is unanimous"
),
"unanimous"
);
}
Assert
.
True
(
text
.
Contains
(
"Choosing master arbitrarily"
),
"arbitrarily"
);
}
}
}
}
\ No newline at end of file
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment