"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
add another email notification test case
To:
gameoftrees@openbsd.org
Date:
Fri, 14 Feb 2025 17:46:51 +0100

Download raw body.

Thread
This adds a test case for email notification where a tag and modified
file are sent to the server in the same operation.

There was a problem with notifications when I sent the 0.109 tag in
combination with a modified CHANGES file earlier today, where the gotd
notify process died. However, this test does not (yet?) reproduce this
particular issue.

Each notifciation causes a separate invocation of got-notify-email
and thus 2 connections are made in this test case.
I needed to add another custom Perl server for this because the nc-based
hacks cannot deal with multiple SMTP connections. This is too limited for
testing non-basic scenarios so I would like to propose my smtp-server
script for inclusion in the test suite.


Does this smtp-server script look fine?
It adds a dependency on yet another perl cpan module but this can
easily be installed from packages.

If this approach looks fine then I would like to replace the use
of nc -l hacks in the other tests with this new script as well.

ok?


add email notification test case for tag creation + file modifiation

M  regress/gotd/README                 |    1+  1-
M  regress/gotd/email_notification.sh  |  109+  0-
A  regress/gotd/smtp-server            |   81+  0-

3 files changed, 191 insertions(+), 1 deletion(-)

commit - f8922f66df0a859909cd8cbbab47888484cd7472
commit + 24c03e0c37fedbf06c192be320272efbf5a92ba6
blob - 0709a766c3b43610a20290c1e889d0ba50846d4c
blob + faa5431af74cec9f5cfa7792534d3554f94b6ad5
--- regress/gotd/README
+++ regress/gotd/README
@@ -51,7 +51,7 @@ sshd must be restarted for configuration changes to ta
 
 The server test suite can now be run from the top-level directory:
 
- $ doas pkg_add git p5-http-daemon p5-digest-hmac
+ $ doas pkg_add git p5-http-daemon p5-digest-hmac p5-net-daemon
  $ doas make server-regress
 
 The suite must be started as root in order to be able to start and stop gotd.
blob - a394b238427aae690c7afae614a4e0e6b9de122d
blob + b006f86ca11e0d1c8226fdee8bd96e7d6dfee32f
--- regress/gotd/email_notification.sh
+++ regress/gotd/email_notification.sh
@@ -631,6 +631,114 @@ test_file_empty() {
 	test_done "$testroot" "$ret"
 }
 
+test_tag_and_commit_created() {
+	local testroot=`test_init tag_and_commit_created 1`
+
+	got clone -a -q ${GOTD_TEST_REPO_URL} $testroot/repo-clone
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "got clone failed unexpectedly" >&2
+		test_done "$testroot" 1
+		return 1
+	fi
+
+	got checkout -q $testroot/repo-clone $testroot/wt >/dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "got checkout failed unexpectedly" >&2
+		test_done "$testroot" 1
+		return 1
+	fi
+
+	echo "change alpha" > $testroot/wt/alpha
+	(cd $testroot/wt && got commit -m 'make changes' > /dev/null)
+	local commit_id=`git_show_head $testroot/repo-clone`
+	local author_time=`git_show_author_time $testroot/repo-clone`
+
+	got tag -r $testroot/repo-clone -m "new tag" 1.1 > /dev/null
+	local commit_id=`git_show_head $testroot/repo-clone`
+	local tagger_time=`git_show_tagger_time $testroot/repo-clone 1.1`
+	local tag_id=`got ref -r $testroot/repo-clone -l \
+		| grep "^refs/tags/1.1" | tr -d ' ' | cut -d: -f2`
+	local short_tag_id=`trim_obj_id 12 $tag_id`
+
+	./smtp-server -p $GOTD_TEST_SMTP_PORT -r 2 \
+		> $testroot/stdout 2>$testroot/stderr &
+
+	sleep 1 # server starts up
+
+	got send -t 1.1 -q -r $testroot/repo-clone
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		echo "got send failed unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	wait %1 # wait for smtp-server
+
+	HOSTNAME=`hostname`
+	short_commit_id=`trim_obj_id 12 $commit_id`
+
+	printf "HELO localhost\r\n" > $testroot/stdout.expected
+	printf "MAIL FROM:<${GOTD_USER}@${HOSTNAME}>\r\n" \
+		>> $testroot/stdout.expected
+	printf "RCPT TO:<${GOTD_DEVUSER}>\r\n" >> $testroot/stdout.expected
+	printf "DATA\r\n" >> $testroot/stdout.expected
+	printf "From: ${GOTD_USER}@${HOSTNAME}\r\n" >> $testroot/stdout.expected
+	printf "To: ${GOTD_DEVUSER}\r\n" >> $testroot/stdout.expected
+	printf "Subject: $GOTD_TEST_REPO_NAME: " >> $testroot/stdout.expected
+	printf "${GOTD_DEVUSER} created refs/tags/1.1: $short_tag_id\r\n" \
+		>> $testroot/stdout.expected
+	printf "\r\n" >> $testroot/stdout.expected
+	printf "tag refs/tags/1.1\n" >> $testroot/stdout.expected
+	printf "from: $GOT_AUTHOR\n" >> $testroot/stdout.expected
+	d=`date -u -r $tagger_time +"%a %b %e %X %Y UTC"`
+	printf "date: $d\n" >> $testroot/stdout.expected
+	printf "object: commit $commit_id\n" >> $testroot/stdout.expected
+	printf "messagelen: 9\n" >> $testroot/stdout.expected
+	printf " \n" >> $testroot/stdout.expected
+	printf " new tag\n \n" >> $testroot/stdout.expected
+	printf "\r\n" >> $testroot/stdout.expected
+	printf ".\r\n" >> $testroot/stdout.expected
+	printf "QUIT\r\n" >> $testroot/stdout.expected
+	printf "HELO localhost\r\n" >> $testroot/stdout.expected
+	printf "MAIL FROM:<${GOTD_USER}@${HOSTNAME}>\r\n" \
+		>> $testroot/stdout.expected
+	printf "RCPT TO:<${GOTD_DEVUSER}>\r\n" >> $testroot/stdout.expected
+	printf "DATA\r\n" >> $testroot/stdout.expected
+	printf "From: ${GOTD_USER}@${HOSTNAME}\r\n" >> $testroot/stdout.expected
+	printf "To: ${GOTD_DEVUSER}\r\n" >> $testroot/stdout.expected
+	printf "Subject: $GOTD_TEST_REPO_NAME: " >> $testroot/stdout.expected
+	printf "${GOTD_DEVUSER} changed refs/heads/main: $short_commit_id\r\n" \
+		>> $testroot/stdout.expected
+	printf "\r\n" >> $testroot/stdout.expected
+	printf "commit $commit_id\n" >> $testroot/stdout.expected
+	printf "from: $GOT_AUTHOR\n" >> $testroot/stdout.expected
+	d=`date -u -r $author_time +"%a %b %e %X %Y UTC"`
+	printf "date: $d\n" >> $testroot/stdout.expected
+	printf "messagelen: 14\n" >> $testroot/stdout.expected
+	printf " \n" >> $testroot/stdout.expected
+	printf " make changes\n \n" >> $testroot/stdout.expected
+	printf " M  alpha  |  1+  0-\n\n"  >> $testroot/stdout.expected
+	printf "1 file changed, 1 insertion(+), 0 deletions(-)\n\n" \
+		>> $testroot/stdout.expected
+	printf "\r\n" >> $testroot/stdout.expected
+	printf ".\r\n" >> $testroot/stdout.expected
+	printf "QUIT\r\n" >> $testroot/stdout.expected
+
+	grep -v ^Date $testroot/stdout > $testroot/stdout.filtered
+	cmp -s $testroot/stdout.expected $testroot/stdout.filtered
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout.filtered
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	test_done "$testroot" "$ret"
+}
+
 test_parseargs "$@"
 run_test test_file_changed
 run_test test_many_commits_not_summarized
@@ -640,3 +748,4 @@ run_test test_branch_removed
 run_test test_tag_created
 run_test test_tag_changed
 run_test test_file_empty
+run_test test_tag_and_commit_created
blob - /dev/null
blob + e21f18c0ac2c63f52e3a11dcdb425253fa4fc022 (mode 755)
--- /dev/null
+++ regress/gotd/smtp-server
@@ -0,0 +1,81 @@
+#!/usr/bin/env perl
+#
+# Copyright (c) 2025 Stefan Sperling <stsp@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+# # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+require Net::Daemon;
+
+package GOTDSMTPServer;
+our @ISA = qw(Net::Daemon);
+
+our $rounds = 1;
+
+sub Run ($) {
+	my ($self) = @_;
+	my ($line, $sock, $rc);
+	my @smtp_codes = (220, 250, 250, 250, 354, 250, 221);
+
+	$sock = $self->{'socket'};
+	foreach (@smtp_codes) {
+		$rc = printf $sock "$_\r\n";
+		if (!$rc) {
+			$self->Error("Client connection error %s",
+			$sock->error());
+			$sock->close();
+			kill(SIGTERM, $$);
+			return;
+		}
+		if (!defined($line = $sock->getline())) {
+			if ($sock->error()) {
+				$self->Error("Client connection error %s",
+				$sock->error());
+			}
+			$sock->close();
+			kill(SIGTERM, $$);
+			return;
+		}
+		print $line;
+	}
+
+	while (1) {
+		if (!defined($line = $sock->getline())) {
+			if ($sock->error()) {
+				$self->Error("Client connection error %s",
+				$sock->error());
+			}
+			$sock->close();
+			$rounds -= 1;
+			if ($rounds > 0) {
+				return;
+			} else {
+				kill(SIGTERM, $$);
+			}
+		}
+		print $line;
+	}
+}
+
+package main;
+
+use Getopt::Long qw(:config bundling);
+
+my $port = 2525;
+
+GetOptions("p:i" => \$port, "r:i" => \$rounds) or die("usage: $0 [-p port] [-r rounds]\n");
+
+my $server = GOTDSMTPServer->new({'pidfile' => 'none', 'mode' => 'single', \
+	'localaddr' => 127.0.0.1, 'localport' => 2525}, \@ARGV);
+
+STDOUT->autoflush(1);
+
+$server->Bind();