Skip to content

Commit df61498

Browse files
authored
Merge pull request #884 from SentinelSoftware/refactor-test-fixture
Refactor: extracted RabbitMQ node management functions from IntegrationFixture
2 parents 05d0930 + 2256d20 commit df61498

File tree

2 files changed

+345
-230
lines changed

2 files changed

+345
-230
lines changed

projects/Unit/Fixtures.cs

Lines changed: 11 additions & 230 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,13 @@
4242

4343
using System;
4444
using System.Collections.Generic;
45-
using System.Diagnostics;
46-
using System.IO;
47-
using System.Linq;
4845
using System.Text;
49-
using System.Text.RegularExpressions;
5046
using System.Threading;
5147

5248
using NUnit.Framework;
5349

54-
using RabbitMQ.Client.Framing;
5550
using RabbitMQ.Client.Framing.Impl;
51+
using static RabbitMQ.Client.Unit.RabbitMQCtl;
5652

5753
namespace RabbitMQ.Client.Unit
5854
{
@@ -62,7 +58,6 @@ public class IntegrationFixture
6258
internal IConnectionFactory ConnFactory;
6359
internal IConnection Conn;
6460
internal IModel Model;
65-
6661
internal Encoding encoding = new UTF8Encoding();
6762
public static TimeSpan RECOVERY_INTERVAL = TimeSpan.FromSeconds(2);
6863

@@ -420,276 +415,62 @@ internal void WaitOn(object o)
420415
}
421416
}
422417

423-
//
424-
// Shelling Out
425-
//
426-
427-
internal Process ExecRabbitMQCtl(string args)
428-
{
429-
// Allow the path to the rabbitmqctl.bat to be set per machine
430-
string envVariable = Environment.GetEnvironmentVariable("RABBITMQ_RABBITMQCTL_PATH");
431-
string rabbitmqctlPath;
432-
433-
if (envVariable != null)
434-
{
435-
var regex = new Regex(@"^DOCKER:(?<dockerMachine>.+)$");
436-
Match match = regex.Match(envVariable);
437-
438-
if (match.Success)
439-
{
440-
return ExecRabbitMqCtlUsingDocker(args, match.Groups["dockerMachine"].Value);
441-
} else {
442-
rabbitmqctlPath = envVariable;
443-
}
444-
}
445-
else
446-
{
447-
// provided by the umbrella
448-
string umbrellaRabbitmqctlPath;
449-
// provided in PATH by a RabbitMQ installation
450-
string providedRabbitmqctlPath;
451-
452-
if (IsRunningOnMonoOrDotNetCore())
453-
{
454-
umbrellaRabbitmqctlPath = "../../../../../../rabbit/scripts/rabbitmqctl";
455-
providedRabbitmqctlPath = "rabbitmqctl";
456-
} else {
457-
umbrellaRabbitmqctlPath = @"..\..\..\..\..\..\rabbit\scripts\rabbitmqctl.bat";
458-
providedRabbitmqctlPath = "rabbitmqctl.bat";
459-
}
460-
461-
if (File.Exists(umbrellaRabbitmqctlPath)) {
462-
rabbitmqctlPath = umbrellaRabbitmqctlPath;
463-
} else {
464-
rabbitmqctlPath = providedRabbitmqctlPath;
465-
}
466-
}
467-
468-
return ExecCommand(rabbitmqctlPath, args);
469-
}
470-
471-
private Process ExecRabbitMqCtlUsingDocker(string args, string dockerMachineName)
472-
{
473-
var proc = new Process
474-
{
475-
StartInfo =
476-
{
477-
CreateNoWindow = true,
478-
UseShellExecute = false
479-
}
480-
};
481-
482-
try {
483-
proc.StartInfo.FileName = "docker";
484-
proc.StartInfo.Arguments = $"exec {dockerMachineName} rabbitmqctl {args}";
485-
proc.StartInfo.RedirectStandardError = true;
486-
proc.StartInfo.RedirectStandardOutput = true;
487-
488-
proc.Start();
489-
string stderr = proc.StandardError.ReadToEnd();
490-
proc.WaitForExit();
491-
if (stderr.Length > 0 || proc.ExitCode > 0)
492-
{
493-
string stdout = proc.StandardOutput.ReadToEnd();
494-
ReportExecFailure("rabbitmqctl", args, $"{stderr}\n{stdout}");
495-
}
496-
497-
return proc;
498-
}
499-
catch (Exception e)
500-
{
501-
ReportExecFailure("rabbitmqctl", args, e.Message);
502-
throw;
503-
}
504-
}
505-
506-
internal Process ExecCommand(string command)
507-
{
508-
return ExecCommand(command, "");
509-
}
510-
511-
internal Process ExecCommand(string command, string args)
512-
{
513-
return ExecCommand(command, args, null);
514-
}
515-
516-
internal Process ExecCommand(string ctl, string args, string changeDirTo)
517-
{
518-
var proc = new Process
519-
{
520-
StartInfo =
521-
{
522-
CreateNoWindow = true,
523-
UseShellExecute = false
524-
}
525-
};
526-
if(changeDirTo != null)
527-
{
528-
proc.StartInfo.WorkingDirectory = changeDirTo;
529-
}
530-
531-
string cmd;
532-
if(IsRunningOnMonoOrDotNetCore()) {
533-
cmd = ctl;
534-
} else {
535-
cmd = "cmd.exe";
536-
args = $"/c \"\"{ctl}\" {args}\"";
537-
}
538-
539-
try {
540-
proc.StartInfo.FileName = cmd;
541-
proc.StartInfo.Arguments = args;
542-
proc.StartInfo.RedirectStandardError = true;
543-
proc.StartInfo.RedirectStandardOutput = true;
544-
545-
proc.Start();
546-
string stderr = proc.StandardError.ReadToEnd();
547-
proc.WaitForExit();
548-
if (stderr.Length > 0 || proc.ExitCode > 0)
549-
{
550-
string stdout = proc.StandardOutput.ReadToEnd();
551-
ReportExecFailure(cmd, args, $"{stderr}\n{stdout}");
552-
}
553-
554-
return proc;
555-
}
556-
catch (Exception e)
557-
{
558-
ReportExecFailure(cmd, args, e.Message);
559-
throw;
560-
}
561-
}
562-
563-
internal void ReportExecFailure(string cmd, string args, string msg)
564-
{
565-
Console.WriteLine($"Failure while running {cmd} {args}:\n{msg}");
566-
}
567-
568-
public static bool IsRunningOnMonoOrDotNetCore()
569-
{
570-
#if NETCOREAPP
571-
return true;
572-
#else
573-
return Type.GetType("Mono.Runtime") != null;
574-
#endif
575-
}
576-
577418
//
578419
// Flow Control
579420
//
580421

581422
internal void Block()
582423
{
583-
ExecRabbitMQCtl("set_vm_memory_high_watermark 0.000000001");
584-
// give rabbitmqctl some time to do its job
585-
Thread.Sleep(1200);
586-
Publish(Conn);
424+
RabbitMQCtl.Block(Conn, encoding);
587425
}
588426

589427
internal void Unblock()
590428
{
591-
ExecRabbitMQCtl("set_vm_memory_high_watermark 0.4");
429+
RabbitMQCtl.Unblock();
592430
}
593431

594432
internal void Publish(IConnection conn)
595433
{
596-
IModel ch = conn.CreateModel();
597-
ch.BasicPublish("amq.fanout", "", null, encoding.GetBytes("message"));
434+
RabbitMQCtl.Publish(conn, encoding);
598435
}
599436

600437
//
601438
// Connection Closure
602439
//
603440

604-
public class ConnectionInfo
605-
{
606-
public string Pid
607-
{
608-
get; set;
609-
}
610-
611-
public string Name
612-
{
613-
get; set;
614-
}
615-
616-
public ConnectionInfo(string pid, string name)
617-
{
618-
Pid = pid;
619-
Name = name;
620-
}
621-
622-
public override string ToString()
623-
{
624-
return $"pid = {Pid}, name: {Name}";
625-
}
626-
}
627-
628-
private static readonly Regex GetConnectionName = new Regex(@"\{""connection_name"",""(?<connection_name>[^""]+)""\}");
629-
630441
internal List<ConnectionInfo> ListConnections()
631442
{
632-
Process proc = ExecRabbitMQCtl("list_connections --silent pid client_properties");
633-
string stdout = proc.StandardOutput.ReadToEnd();
634-
635-
try
636-
{
637-
// {Environment.NewLine} is not sufficient
638-
string[] splitOn = new string[] { "\r\n", "\n" };
639-
string[] lines = stdout.Split(splitOn, StringSplitOptions.RemoveEmptyEntries);
640-
// line: <rabbit@mercurio.1.11491.0> {.../*client_properties*/...}
641-
return lines.Select(s =>
642-
{
643-
string[] columns = s.Split('\t');
644-
Debug.Assert(!string.IsNullOrEmpty(columns[0]), "columns[0] is null or empty!");
645-
Debug.Assert(!string.IsNullOrEmpty(columns[1]), "columns[1] is null or empty!");
646-
Match match = GetConnectionName.Match(columns[1]);
647-
Debug.Assert(match.Success, "columns[1] is not in expected format.");
648-
return new ConnectionInfo(columns[0], match.Groups["connection_name"].Value);
649-
}).ToList();
650-
}
651-
catch (Exception)
652-
{
653-
Console.WriteLine($"Bad response from rabbitmqctl list_connections --silent pid client_properties{Environment.NewLine}{stdout}");
654-
throw;
655-
}
443+
return RabbitMQCtl.ListConnections();
656444
}
657445

658446
internal void CloseConnection(IConnection conn)
659447
{
660-
ConnectionInfo ci = ListConnections().First(x => conn.ClientProvidedName == x.Name);
661-
CloseConnection(ci.Pid);
448+
RabbitMQCtl.CloseConnection(conn);
662449
}
663450

664451
internal void CloseAllConnections()
665452
{
666-
List<ConnectionInfo> cs = ListConnections();
667-
foreach(ConnectionInfo c in cs)
668-
{
669-
CloseConnection(c.Pid);
670-
}
453+
RabbitMQCtl.CloseAllConnections();
671454
}
672455

673456
internal void CloseConnection(string pid)
674457
{
675-
ExecRabbitMQCtl($"close_connection \"{pid}\" \"Closed via rabbitmqctl\"");
458+
RabbitMQCtl.CloseConnection(pid);
676459
}
677460

678461
internal void RestartRabbitMQ()
679462
{
680-
StopRabbitMQ();
681-
Thread.Sleep(500);
682-
StartRabbitMQ();
463+
RabbitMQCtl.RestartRabbitMQ();
683464
}
684465

685466
internal void StopRabbitMQ()
686467
{
687-
ExecRabbitMQCtl("stop_app");
468+
RabbitMQCtl.StopRabbitMQ();
688469
}
689470

690471
internal void StartRabbitMQ()
691472
{
692-
ExecRabbitMQCtl("start_app");
473+
RabbitMQCtl.StartRabbitMQ();
693474
}
694475

695476
//

0 commit comments

Comments
 (0)