Make Address an AutoValue

Address is a data-holder for an RFC email address. Making it an
AutoValue signifies to callers that it's immutable, hence thread-safe.

Change-Id: I9deb50145d10feb93eca540701944cea6428f9d1
This commit is contained in:
Patrick Hiesel
2020-04-22 16:26:40 +02:00
parent e96815ac36
commit b13175a9fb
42 changed files with 186 additions and 193 deletions

View File

@@ -1277,7 +1277,7 @@ public abstract class AbstractDaemonTest {
}
protected void assertNotifyTo(String expectedEmail, String expectedFullname) {
Address expectedAddress = new Address(expectedFullname, expectedEmail);
Address expectedAddress = Address.create(expectedFullname, expectedEmail);
assertThat(sender.getMessages()).hasSize(1);
Message m = sender.getMessages().get(0);
assertThat(m.rcpt()).containsExactly(expectedAddress);
@@ -1291,7 +1291,7 @@ public abstract class AbstractDaemonTest {
}
protected void assertNotifyCc(String expectedEmail, String expectedFullname) {
Address expectedAddress = new Address(expectedFullname, expectedEmail);
Address expectedAddress = Address.create(expectedFullname, expectedEmail);
assertNotifyCc(expectedAddress);
}
@@ -1315,7 +1315,7 @@ public abstract class AbstractDaemonTest {
protected void assertNotifyBcc(String expectedEmail, String expectedFullName) {
assertThat(sender.getMessages()).hasSize(1);
Message m = sender.getMessages().get(0);
assertThat(m.rcpt()).containsExactly(new Address(expectedFullName, expectedEmail));
assertThat(m.rcpt()).containsExactly(Address.create(expectedFullName, expectedEmail));
assertThat(m.headers().get("To").isEmpty()).isTrue();
assertThat(m.headers().get("Cc").isEmpty()).isTrue();
}

View File

@@ -126,7 +126,7 @@ public abstract class AbstractNotificationTest extends AbstractDaemonTest {
recipients.put(
BCC,
message.rcpt().stream()
.map(Address::getEmail)
.map(Address::email)
.filter(e -> !recipients.get(TO).contains(e) && !recipients.get(CC).contains(e))
.collect(toList()));
this.users = users;
@@ -174,7 +174,7 @@ public abstract class AbstractNotificationTest extends AbstractDaemonTest {
}
Truth.assertThat(header).isInstanceOf(AddressList.class);
AddressList addrList = (AddressList) header;
return addrList.getAddressList().stream().map(Address::getEmail).collect(toList());
return addrList.getAddressList().stream().map(Address::email).collect(toList());
}
public FakeEmailSenderSubject to(String... emails) {

View File

@@ -92,6 +92,6 @@ public abstract class TestAccount {
// emailAddress().
// * Address#equals only considers email, not name, whereas TestAccount#equals should include
// name.
return new Address(fullName(), email());
return Address.create(fullName(), email());
}
}

View File

@@ -14,10 +14,12 @@
package com.google.gerrit.mail;
import com.google.auto.value.AutoValue;
import com.google.gerrit.common.Nullable;
/** Represents an address (name + email) in an email message. */
public class Address {
@AutoValue
public abstract class Address {
public static Address parse(String in) {
final int lt = in.indexOf('<');
final int gt = in.indexOf('>');
@@ -33,11 +35,11 @@ public class Address {
if (name.endsWith("\"")) {
nameEnd--;
}
return new Address(name.length() > 0 ? name.substring(nameStart, nameEnd) : null, email);
return Address.create(name.length() > 0 ? name.substring(nameStart, nameEnd) : null, email);
}
if (lt < 0 && gt < 0 && 0 < at && at < in.length() - 1) {
return new Address(in);
return Address.create(in);
}
throw new IllegalArgumentException("Invalid email address: " + in);
@@ -51,60 +53,52 @@ public class Address {
}
}
@Nullable private final String name;
private final String email;
public Address(String email) {
this(null, email);
public static Address create(String email) {
return create(null, email);
}
public Address(String name, String email) {
this.name = name;
this.email = email;
public static Address create(String name, String email) {
return new AutoValue_Address(name, email);
}
@Nullable
public String getName() {
return name;
}
public abstract String name();
public String getEmail() {
return email;
public abstract String email();
@Override
public final int hashCode() {
return email().hashCode();
}
@Override
public int hashCode() {
return email.hashCode();
}
@Override
public boolean equals(Object other) {
public final boolean equals(Object other) {
if (other instanceof Address) {
return email.equals(((Address) other).email);
return email().equals(((Address) other).email());
}
return false;
}
@Override
public String toString() {
public final String toString() {
return toHeaderString();
}
public String toHeaderString() {
if (name != null) {
return quotedPhrase(name) + " <" + email + ">";
if (name() != null) {
return quotedPhrase(name()) + " <" + email() + ">";
} else if (isSimple()) {
return email;
return email();
}
return "<" + email + ">";
return "<" + email() + ">";
}
private static final String MUST_QUOTE_EMAIL = "()<>,;:\\\"[]";
private static final String MUST_QUOTE_NAME = MUST_QUOTE_EMAIL + "@.";
private boolean isSimple() {
for (int i = 0; i < email.length(); i++) {
final char c = email.charAt(i);
for (int i = 0; i < email().length(); i++) {
final char c = email().charAt(i);
if (c <= ' ' || 0x7F <= c || MUST_QUOTE_EMAIL.indexOf(c) != -1) {
return false;
}

View File

@@ -183,7 +183,7 @@ public abstract class EmailHeader {
}
public void remove(java.lang.String email) {
list.removeIf(address -> address.getEmail().equals(email));
list.removeIf(address -> address.email().equals(email));
}
@Override

View File

@@ -29,7 +29,7 @@ public class MailHeaderParser {
public static MailMetadata parse(MailMessage m) {
MailMetadata metadata = new MailMetadata();
// Find author
metadata.author = m.from().getEmail();
metadata.author = m.from().email();
// Check email headers for X-Gerrit-<Name>
for (String header : m.additionalHeaders()) {

View File

@@ -71,16 +71,16 @@ public class RawMailParser {
// Add From, To and Cc
if (mimeMessage.getFrom() != null && !mimeMessage.getFrom().isEmpty()) {
Mailbox from = mimeMessage.getFrom().get(0);
messageBuilder.from(new Address(from.getName(), from.getAddress()));
messageBuilder.from(Address.create(from.getName(), from.getAddress()));
}
if (mimeMessage.getTo() != null) {
for (Mailbox m : mimeMessage.getTo().flatten()) {
messageBuilder.addTo(new Address(m.getName(), m.getAddress()));
messageBuilder.addTo(Address.create(m.getName(), m.getAddress()));
}
}
if (mimeMessage.getCc() != null) {
for (Mailbox m : mimeMessage.getCc().flatten()) {
messageBuilder.addCc(new Address(m.getName(), m.getAddress()));
messageBuilder.addCc(Address.create(m.getName(), m.getAddress()));
}
}

View File

@@ -786,7 +786,7 @@ public class ChangeJson {
private Collection<AccountInfo> toAccountInfoByEmail(Collection<Address> addresses) {
return addresses.stream()
.map(a -> new AccountInfo(a.getName(), a.getEmail()))
.map(a -> new AccountInfo(a.name(), a.email()))
.sorted(AccountInfoComparator.ORDER_NULLS_FIRST)
.collect(toList());
}

View File

@@ -379,7 +379,7 @@ public class ReviewerAdder {
}
Address adr = Address.tryParse(input.reviewer);
if (adr == null || !validator.isValid(adr.getEmail())) {
if (adr == null || !validator.isValid(adr.email())) {
return fail(
input,
FailureType.NOT_FOUND,
@@ -481,7 +481,7 @@ public class ReviewerAdder {
}
accountLoaderFactory.create(true).fill(result.ccs);
for (Address a : opResult.addedCCsByEmail()) {
result.ccs.add(new AccountInfo(a.getName(), a.getEmail()));
result.ccs.add(new AccountInfo(a.name(), a.email()));
}
} else {
result.reviewers = Lists.newArrayListWithCapacity(opResult.addedReviewers().size());
@@ -496,7 +496,7 @@ public class ReviewerAdder {
}
accountLoaderFactory.create(true).fill(result.reviewers);
for (Address a : opResult.addedReviewersByEmail()) {
result.reviewers.add(ReviewerInfo.byEmail(a.getName(), a.getEmail()));
result.reviewers.add(ReviewerInfo.byEmail(a.name(), a.email()));
}
}
}

View File

@@ -75,7 +75,7 @@ public class ReviewerJson {
ReviewerInfo info;
if (rsrc.isByEmail()) {
Address address = rsrc.getReviewerByEmail();
info = ReviewerInfo.byEmail(address.getName(), address.getEmail());
info = ReviewerInfo.byEmail(address.name(), address.email());
} else {
Account.Id reviewerAccountId = rsrc.getReviewerUser().getAccountId();
info = format(new ReviewerInfo(reviewerAccountId.get()), reviewerAccountId, cd);

View File

@@ -384,9 +384,9 @@ public class ChangeField {
reviewersByEmail.asTable().cellSet()) {
String v = getReviewerByEmailFieldValue(c.getRowKey(), c.getColumnKey());
r.add(v);
if (c.getColumnKey().getName() != null) {
if (c.getColumnKey().name() != null) {
// Add another entry without the name to provide search functionality on the email
Address emailOnly = new Address(c.getColumnKey().getEmail());
Address emailOnly = Address.create(c.getColumnKey().email());
r.add(getReviewerByEmailFieldValue(c.getRowKey(), emailOnly));
}
r.add(v + ',' + c.getValue().getTime());

View File

@@ -52,7 +52,7 @@ public class ListMailFilter implements MailFilter {
return true;
}
boolean match = mailPattern.matcher(message.from().getEmail()).find();
boolean match = mailPattern.matcher(message.from().email()).find();
if ((mode == ListFilterMode.WHITELIST && !match)
|| (mode == ListFilterMode.BLACKLIST && match)) {
logger.atInfo().log("Mail message from %s rejected by list filter", message.from());

View File

@@ -58,7 +58,7 @@ public class AddKeySender extends OutgoingEmail {
protected void init() throws EmailException {
super.init();
setHeader("Subject", String.format("[Gerrit Code Review] New %s Keys Added", getKeyType()));
add(RecipientType.TO, new Address(getEmail()));
add(RecipientType.TO, Address.create(getEmail()));
}
@Override

View File

@@ -63,7 +63,7 @@ public class DeleteKeySender extends OutgoingEmail {
protected void init() throws EmailException {
super.init();
setHeader("Subject", String.format("[Gerrit Code Review] %s Keys Deleted", getKeyType()));
add(RecipientType.TO, new Address(getEmail()));
add(RecipientType.TO, Address.create(getEmail()));
}
@Override

View File

@@ -52,8 +52,7 @@ public class FromAddressGeneratorProvider implements Provider<FromAddressGenerat
if (from == null || "MIXED".equalsIgnoreCase(from)) {
ParameterizedString name = new ParameterizedString("${user} (Code Review)");
generator =
new PatternGen(srvAddr, accountCache, anonymousCowardName, name, srvAddr.getEmail());
generator = new PatternGen(srvAddr, accountCache, anonymousCowardName, name, srvAddr.email());
} else if ("USER".equalsIgnoreCase(from)) {
String[] domains = cfg.getStringList("sendemail", null, "allowedDomain");
Pattern domainPattern = MailUtil.glob(domains);
@@ -64,18 +63,17 @@ public class FromAddressGeneratorProvider implements Provider<FromAddressGenerat
generator = new ServerGen(srvAddr);
} else {
final Address a = Address.parse(from);
final ParameterizedString name =
a.getName() != null ? new ParameterizedString(a.getName()) : null;
final ParameterizedString name = a.name() != null ? new ParameterizedString(a.name()) : null;
if (name == null || name.getParameterNames().isEmpty()) {
generator = new ServerGen(a);
} else {
generator = new PatternGen(srvAddr, accountCache, anonymousCowardName, name, a.getEmail());
generator = new PatternGen(srvAddr, accountCache, anonymousCowardName, name, a.email());
}
}
}
private static Address toAddress(PersonIdent myIdent) {
return new Address(myIdent.getName(), myIdent.getEmailAddress());
return Address.create(myIdent.getName(), myIdent.getEmailAddress());
}
@Override
@@ -127,7 +125,7 @@ public class FromAddressGeneratorProvider implements Provider<FromAddressGenerat
String fullName = a.map(Account::fullName).orElse(null);
String userEmail = a.map(Account::preferredEmail).orElse(null);
if (canRelay(userEmail)) {
return new Address(fullName, userEmail);
return Address.create(fullName, userEmail);
}
if (fullName == null || "".equals(fullName.trim())) {
@@ -135,17 +133,17 @@ public class FromAddressGeneratorProvider implements Provider<FromAddressGenerat
}
senderName = nameRewriteTmpl.replace("user", fullName).toString();
} else {
senderName = serverAddress.getName();
senderName = serverAddress.name();
}
String senderEmail;
ParameterizedString senderEmailPattern = new ParameterizedString(serverAddress.getEmail());
ParameterizedString senderEmailPattern = new ParameterizedString(serverAddress.email());
if (senderEmailPattern.getParameterNames().isEmpty()) {
senderEmail = senderEmailPattern.getRawPattern();
} else {
senderEmail = senderEmailPattern.replace("userHash", hashOf(senderName)).toString();
}
return new Address(senderName, senderEmail);
return Address.create(senderName, senderEmail);
}
/** check if Gerrit is allowed to send from {@code userEmail}. */
@@ -215,7 +213,7 @@ public class FromAddressGeneratorProvider implements Provider<FromAddressGenerat
senderName = namePattern.replace("user", fullName).toString();
} else {
senderName = serverAddress.getName();
senderName = serverAddress.name();
}
String senderEmail;
@@ -224,7 +222,7 @@ public class FromAddressGeneratorProvider implements Provider<FromAddressGenerat
} else {
senderEmail = senderEmailPattern.replace("userHash", hashOf(senderName)).toString();
}
return new Address(senderName, senderEmail);
return Address.create(senderName, senderEmail);
}
}

View File

@@ -42,7 +42,7 @@ public class HttpPasswordUpdateSender extends OutgoingEmail {
protected void init() throws EmailException {
super.init();
setHeader("Subject", "[Gerrit Code Review] HTTP password was " + operation);
add(RecipientType.TO, new Address(getEmail()));
add(RecipientType.TO, Address.create(getEmail()));
}
@Override

View File

@@ -162,7 +162,7 @@ public abstract class OutgoingEmail {
"Removing account %s from HTML email because user prefers plain text emails", id);
removeUser(thisUserAccount);
smtpRcptToPlaintextOnly.add(
new Address(thisUserAccount.fullName(), thisUserAccount.preferredEmail()));
Address.create(thisUserAccount.fullName(), thisUserAccount.preferredEmail()));
}
}
if (smtpRcptTo.isEmpty() && smtpRcptToPlaintextOnly.isEmpty()) {
@@ -179,11 +179,11 @@ public abstract class OutgoingEmail {
if (fromId != null) {
Address address = toAddress(fromId);
if (address != null) {
j.add(address.getEmail());
j.add(address.email());
}
}
smtpRcptTo.stream().forEach(a -> j.add(a.getEmail()));
smtpRcptToPlaintextOnly.stream().forEach(a -> j.add(a.getEmail()));
smtpRcptTo.stream().forEach(a -> j.add(a.email()));
smtpRcptToPlaintextOnly.stream().forEach(a -> j.add(a.email()));
setHeader(FieldName.REPLY_TO, j.toString());
}
@@ -518,16 +518,16 @@ public abstract class OutgoingEmail {
}
protected void add(RecipientType rt, Address addr, boolean override) {
if (addr != null && addr.getEmail() != null && addr.getEmail().length() > 0) {
if (!args.validator.isValid(addr.getEmail())) {
logger.atWarning().log("Not emailing %s (invalid email address)", addr.getEmail());
} else if (args.emailSender.canEmail(addr.getEmail())) {
if (addr != null && addr.email() != null && addr.email().length() > 0) {
if (!args.validator.isValid(addr.email())) {
logger.atWarning().log("Not emailing %s (invalid email address)", addr.email());
} else if (args.emailSender.canEmail(addr.email())) {
if (!smtpRcptTo.add(addr)) {
if (!override) {
return;
}
((EmailHeader.AddressList) headers.get(FieldName.TO)).remove(addr.getEmail());
((EmailHeader.AddressList) headers.get(FieldName.CC)).remove(addr.getEmail());
((EmailHeader.AddressList) headers.get(FieldName.TO)).remove(addr.email());
((EmailHeader.AddressList) headers.get(FieldName.CC)).remove(addr.email());
}
switch (rt) {
case TO:
@@ -554,7 +554,7 @@ public abstract class OutgoingEmail {
if (!account.isActive() || e == null) {
return null;
}
return new Address(account.fullName(), e);
return Address.create(account.fullName(), e);
}
protected void setupSoyContext() {
@@ -597,7 +597,7 @@ public abstract class OutgoingEmail {
protected void removeUser(Account user) {
String fromEmail = user.preferredEmail();
for (Iterator<Address> j = smtpRcptTo.iterator(); j.hasNext(); ) {
if (j.next().getEmail().equals(fromEmail)) {
if (j.next().email().equals(fromEmail)) {
j.remove();
}
}

View File

@@ -185,7 +185,7 @@ public class ProjectWatch {
}
if (!Strings.isNullOrEmpty(group.getEmailAddress())) {
// If the group has an email address, do not expand membership.
matching.emails.add(new Address(group.getEmailAddress()));
matching.emails.add(Address.create(group.getEmailAddress()));
logger.atFine().log(
"notify group email address %s; skip expanding to members", group.getEmailAddress());
continue;

View File

@@ -54,7 +54,7 @@ public class RegisterNewEmailSender extends OutgoingEmail {
protected void init() throws EmailException {
super.init();
setHeader("Subject", "[Gerrit Code Review] Email Verification");
add(RecipientType.TO, new Address(addr));
add(RecipientType.TO, Address.create(addr));
}
@Override

View File

@@ -206,9 +206,8 @@ public class SmtpEmailSender implements EmailSender {
try {
final SMTPClient client = open();
try {
if (!client.setSender(from.getEmail())) {
throw new EmailException(
"Server " + smtpHost + " rejected from address " + from.getEmail());
if (!client.setSender(from.email())) {
throw new EmailException("Server " + smtpHost + " rejected from address " + from.email());
}
/* Do not prevent the email from being sent to "good" users simply
@@ -219,7 +218,7 @@ public class SmtpEmailSender implements EmailSender {
* error(s) logged.
*/
for (Address addr : rcpt) {
if (!client.addRecipient(addr.getEmail())) {
if (!client.addRecipient(addr.email())) {
String error = client.getReplyString();
rejected
.append("Server ")

View File

@@ -1077,7 +1077,7 @@ public class AccountIT extends AbstractDaemonTest {
assertThat(sender.getMessages()).hasSize(1);
Message m = sender.getMessages().get(0);
assertThat(m.rcpt()).containsExactly(new Address(email));
assertThat(m.rcpt()).containsExactly(Address.create(email));
}
@Test

View File

@@ -1517,7 +1517,7 @@ public class ChangeIT extends AbstractDaemonTest {
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Message m = messages.get(0);
assertThat(m.from().getName()).isEqualTo("Administrator (Code Review)");
assertThat(m.from().name()).isEqualTo("Administrator (Code Review)");
assertThat(m.rcpt()).containsExactly(user.getNameEmail());
assertThat(m.body()).contains("I'd like you to do a code review");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
@@ -1899,7 +1899,7 @@ public class ChangeIT extends AbstractDaemonTest {
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(new Address(fullname, email));
assertThat(m.rcpt()).containsExactly(Address.create(fullname, email));
assertThat(m.body()).contains("Hello " + fullname + ",\n");
assertThat(m.body()).contains("I'd like you to do a code review.");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
@@ -1960,7 +1960,7 @@ public class ChangeIT extends AbstractDaemonTest {
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(new Address(myGroupUserFullname, myGroupUserEmail));
assertThat(m.rcpt()).containsExactly(Address.create(myGroupUserFullname, myGroupUserEmail));
assertThat(m.body()).contains("Hello " + myGroupUserFullname + ",\n");
assertThat(m.body()).contains("I'd like you to do a code review.");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
@@ -4461,7 +4461,7 @@ public class ChangeIT extends AbstractDaemonTest {
amendChange(r.getChangeId());
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Address address = new Address(fullname, email);
Address address = Address.create(fullname, email);
assertThat(messages.get(0).rcpt()).containsExactly(address);
// Review notification is not sent to users ignoring the change

View File

@@ -1851,7 +1851,8 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
@Test
public void pushWithEmailInFooterNotFound() throws Exception {
pushWithReviewerInFooter(new Address("No Body", "notarealuser@example.com").toString(), null);
pushWithReviewerInFooter(
Address.create("No Body", "notarealuser@example.com").toString(), null);
}
@Test

View File

@@ -514,7 +514,7 @@ public class SubmitOnPushIT extends AbstractDaemonTest {
TestAccount expected, @Nullable RecipientType expectedRecipientType) {
String expectedEmail = expected.email();
String expectedFullName = expected.fullName();
Address expectedAddress = new Address(expectedFullName, expectedEmail);
Address expectedAddress = Address.create(expectedFullName, expectedEmail);
assertThat(sender.getMessages()).hasSize(2);
Message message = sender.getMessages().get(0);
assertThat(message.body().contains("review")).isTrue();

View File

@@ -368,6 +368,6 @@ public class ChangeReviewersByEmailIT extends AbstractDaemonTest {
}
private static String toRfcAddressString(AccountInfo info) {
return (new Address(info.name, info.email)).toString();
return (Address.create(info.name, info.email)).toString();
}
}

View File

@@ -830,7 +830,7 @@ public class ChangeReviewersIT extends AbstractDaemonTest {
}
private void assertThatUserIsOnlyReviewer(String changeId) throws Exception {
AccountInfo userInfo = new AccountInfo(user.fullName(), user.getNameEmail().getEmail());
AccountInfo userInfo = new AccountInfo(user.fullName(), user.getNameEmail().email());
userInfo._accountId = user.id().get();
userInfo.username = user.username();
assertThat(gApi.changes().id(changeId).get().reviewers)

View File

@@ -303,7 +303,7 @@ public class CreateChangeIT extends AbstractDaemonTest {
assertThat(author).email().isEqualTo(input.author.email);
assertThat(author).name().isEqualTo(input.author.name);
GitPerson committer = rApi.commit(false).committer;
assertThat(committer).email().isEqualTo(admin.getNameEmail().getEmail());
assertThat(committer).email().isEqualTo(admin.getNameEmail().email());
}
@Test
@@ -463,7 +463,7 @@ public class CreateChangeIT extends AbstractDaemonTest {
GitPerson author = rApi.commit(false).author;
assertThat(author).email().isEqualTo(in.author.email);
GitPerson committer = rApi.commit(false).committer;
assertThat(committer).email().isEqualTo(admin.getNameEmail().getEmail());
assertThat(committer).email().isEqualTo(admin.getNameEmail().email());
}
@Test

View File

@@ -49,7 +49,7 @@ public class ProjectWatchIT extends AbstractDaemonTest {
@Test
public void newPatchSetsNotifyConfig() throws Exception {
Address addr = new Address("Watcher", "watcher@example.com");
Address addr = Address.create("Watcher", "watcher@example.com");
NotifyConfig nc = new NotifyConfig();
nc.addEmail(addr);
nc.setName("new-patch-set");
@@ -90,7 +90,7 @@ public class ProjectWatchIT extends AbstractDaemonTest {
@Test
public void noNotificationForPrivateChangesForWatchersInNotifyConfig() throws Exception {
Address addr = new Address("Watcher", "watcher@example.com");
Address addr = Address.create("Watcher", "watcher@example.com");
NotifyConfig nc = new NotifyConfig();
nc.addEmail(addr);
nc.setName("team");
@@ -122,7 +122,7 @@ public class ProjectWatchIT extends AbstractDaemonTest {
@Test
public void noNotificationForChangeThatIsTurnedPrivateForWatchersInNotifyConfig()
throws Exception {
Address addr = new Address("Watcher", "watcher@example.com");
Address addr = Address.create("Watcher", "watcher@example.com");
NotifyConfig nc = new NotifyConfig();
nc.addEmail(addr);
nc.setName("team");
@@ -151,7 +151,7 @@ public class ProjectWatchIT extends AbstractDaemonTest {
@Test
public void noNotificationForWipChangesForWatchersInNotifyConfig() throws Exception {
Address addr = new Address("Watcher", "watcher@example.com");
Address addr = Address.create("Watcher", "watcher@example.com");
NotifyConfig nc = new NotifyConfig();
nc.addEmail(addr);
nc.setName("team");
@@ -182,7 +182,7 @@ public class ProjectWatchIT extends AbstractDaemonTest {
@Test
public void noNotificationForChangeThatIsTurnedWipForWatchersInNotifyConfig() throws Exception {
Address addr = new Address("Watcher", "watcher@example.com");
Address addr = Address.create("Watcher", "watcher@example.com");
NotifyConfig nc = new NotifyConfig();
nc.addEmail(addr);
nc.setName("team");

View File

@@ -84,7 +84,7 @@ public class AbstractParserTest {
protected static MailMessage.Builder newMailMessageBuilder() {
MailMessage.Builder b = MailMessage.builder();
b.id("id");
b.from(new Address("Foo Bar", "foo@bar.com"));
b.from(Address.create("Foo Bar", "foo@bar.com"));
b.dateReceived(Instant.now());
b.subject("");
return b;

View File

@@ -23,57 +23,57 @@ public class AddressTest {
@Test
public void parse_NameEmail1() {
final Address a = Address.parse("A U Thor <author@example.com>");
assertThat(a.getName()).isEqualTo("A U Thor");
assertThat(a.getEmail()).isEqualTo("author@example.com");
assertThat(a.name()).isEqualTo("A U Thor");
assertThat(a.email()).isEqualTo("author@example.com");
}
@Test
public void parse_NameEmail2() {
final Address a = Address.parse("A <a@b>");
assertThat(a.getName()).isEqualTo("A");
assertThat(a.getEmail()).isEqualTo("a@b");
assertThat(a.name()).isEqualTo("A");
assertThat(a.email()).isEqualTo("a@b");
}
@Test
public void parse_NameEmail3() {
final Address a = Address.parse("<a@b>");
assertThat(a.getName()).isNull();
assertThat(a.getEmail()).isEqualTo("a@b");
assertThat(a.name()).isNull();
assertThat(a.email()).isEqualTo("a@b");
}
@Test
public void parse_NameEmail4() {
final Address a = Address.parse("A U Thor<author@example.com>");
assertThat(a.getName()).isEqualTo("A U Thor");
assertThat(a.getEmail()).isEqualTo("author@example.com");
assertThat(a.name()).isEqualTo("A U Thor");
assertThat(a.email()).isEqualTo("author@example.com");
}
@Test
public void parse_NameEmail5() {
final Address a = Address.parse("A U Thor <author@example.com>");
assertThat(a.getName()).isEqualTo("A U Thor");
assertThat(a.getEmail()).isEqualTo("author@example.com");
assertThat(a.name()).isEqualTo("A U Thor");
assertThat(a.email()).isEqualTo("author@example.com");
}
@Test
public void parse_Email1() {
final Address a = Address.parse("author@example.com");
assertThat(a.getName()).isNull();
assertThat(a.getEmail()).isEqualTo("author@example.com");
assertThat(a.name()).isNull();
assertThat(a.email()).isEqualTo("author@example.com");
}
@Test
public void parse_Email2() {
final Address a = Address.parse("a@b");
assertThat(a.getName()).isNull();
assertThat(a.getEmail()).isEqualTo("a@b");
assertThat(a.name()).isNull();
assertThat(a.email()).isEqualTo("a@b");
}
@Test
public void parse_NewTLD() {
Address a = Address.parse("A U Thor <author@example.systems>");
assertThat(a.getName()).isEqualTo("A U Thor");
assertThat(a.getEmail()).isEqualTo("author@example.systems");
assertThat(a.name()).isEqualTo("A U Thor");
assertThat(a.email()).isEqualTo("author@example.systems");
}
@Test
@@ -148,6 +148,6 @@ public class AddressTest {
}
private static String format(String name, String email) {
return new Address(name, email).toHeaderString();
return Address.create(name, email).toHeaderString();
}
}

View File

@@ -38,11 +38,11 @@ public class MailHeaderParserTest {
b.addAdditionalHeader(
MailHeader.COMMENT_DATE.fieldWithDelimiter() + "Tue, 25 Oct 2016 02:11:35 -0700");
Address author = new Address("Diffy", "test@gerritcodereview.com");
Address author = Address.create("Diffy", "test@gerritcodereview.com");
b.from(author);
MailMetadata meta = MailHeaderParser.parse(b.build());
assertThat(meta.author).isEqualTo(author.getEmail());
assertThat(meta.author).isEqualTo(author.email());
assertThat(meta.changeNumber).isEqualTo(123);
assertThat(meta.patchSet).isEqualTo(1);
assertThat(meta.messageType).isEqualTo("comment");
@@ -71,11 +71,11 @@ public class MailHeaderParserTest {
.append("Tue, 25 Oct 2016 02:11:35 -0700\r\n");
b.textContent(stringBuilder.toString());
Address author = new Address("Diffy", "test@gerritcodereview.com");
Address author = Address.create("Diffy", "test@gerritcodereview.com");
b.from(author);
MailMetadata meta = MailHeaderParser.parse(b.build());
assertThat(meta.author).isEqualTo(author.getEmail());
assertThat(meta.author).isEqualTo(author.email());
assertThat(meta.changeNumber).isEqualTo(123);
assertThat(meta.patchSet).isEqualTo(1);
assertThat(meta.messageType).isEqualTo("comment");
@@ -112,11 +112,11 @@ public class MailHeaderParserTest {
.append("</div>");
b.htmlContent(stringBuilder.toString());
Address author = new Address("Diffy", "test@gerritcodereview.com");
Address author = Address.create("Diffy", "test@gerritcodereview.com");
b.from(author);
MailMetadata meta = MailHeaderParser.parse(b.build());
assertThat(meta.author).isEqualTo(author.getEmail());
assertThat(meta.author).isEqualTo(author.email());
assertThat(meta.changeNumber).isEqualTo(123);
assertThat(meta.patchSet).isEqualTo(1);
assertThat(meta.messageType).isEqualTo("comment");

View File

@@ -77,8 +77,8 @@ public class AttachmentMessage extends RawMailMessage {
MailMessage.Builder expect = MailMessage.builder();
expect
.id("<CAM7sg=3meaAVUxW3KXeJEVs8sv_ADw1BnvpcHHiYVR2TQQi__w@mail.gmail.com>")
.from(new Address("Patrick Hiesel", "hiesel@google.com"))
.addTo(new Address("Patrick Hiesel", "hiesel@google.com"))
.from(Address.create("Patrick Hiesel", "hiesel@google.com"))
.addTo(Address.create("Patrick Hiesel", "hiesel@google.com"))
.textContent("Contains unwanted attachment")
.htmlContent("<div dir=\"ltr\">Contains unwanted attachment</div>")
.subject("Test Subject")

View File

@@ -53,10 +53,10 @@ public class Base64HeaderMessage extends RawMailMessage {
expect
.id("<001a114da7ae26e2eb053fe0c29c@google.com>")
.from(
new Address(
Address.create(
"Jonathan Nieder (Gerrit)",
"noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
.addTo(new Address("ekempin", "ekempin@google.com"))
.addTo(Address.create("ekempin", "ekempin@google.com"))
.textContent(textContent)
.subject("\uD83D\uDE1B test")
.dateReceived(

View File

@@ -91,10 +91,10 @@ public class HtmlMimeMessage extends RawMailMessage {
expect
.id("<001a114cd8be55b4ab053face5cd@google.com>")
.from(
new Address(
Address.create(
"ekempin (Gerrit)", "noreply-gerritcodereview-qUgXfQecoDLHwp0MldAzig@google.com"))
.addCc(new Address("ekempin", "ekempin@google.com"))
.addTo(new Address("Patrick Hiesel", "hiesel@google.com"))
.addCc(Address.create("ekempin", "ekempin@google.com"))
.addTo(Address.create("Patrick Hiesel", "hiesel@google.com"))
.textContent(textContent)
.htmlContent(unencodedHtmlContent)
.subject("Change in gerrit[master]: Implement receiver class structure and bindings")

View File

@@ -57,10 +57,10 @@ public class NonUTF8Message extends RawMailMessage {
expect
.id("<001a114da7ae26e2eb053fe0c29c@google.com>")
.from(
new Address(
Address.create(
"Jonathan Nieder (Gerrit)",
"noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
.addTo(new Address("ekempin", "ekempin@google.com"))
.addTo(Address.create("ekempin", "ekempin@google.com"))
.textContent(textContent)
.subject("\uD83D\uDE1B test")
.dateReceived(

View File

@@ -54,10 +54,10 @@ public class QuotedPrintableHeaderMessage extends RawMailMessage {
expect
.id("<001a114da7ae26e2eb053fe0c29c@google.com>")
.from(
new Address(
Address.create(
"Jonathan Nieder (Gerrit)",
"noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
.addTo(new Address("ekempin", "ekempin@google.com"))
.addTo(Address.create("ekempin", "ekempin@google.com"))
.textContent(textContent)
.subject("âme vulgaire")
.dateReceived(

View File

@@ -116,13 +116,13 @@ public class SimpleTextMessage extends RawMailMessage {
expect
.id("<001a114da7ae26e2eb053fe0c29c@google.com>")
.from(
new Address(
Address.create(
"Jonathan Nieder (Gerrit)",
"noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
.addTo(new Address("ekempin", "ekempin@google.com"))
.addCc(new Address("Dave Borowitz", "dborowitz@google.com"))
.addCc(new Address("Jonathan Nieder", "jrn@google.com"))
.addCc(new Address("Patrick Hiesel", "hiesel@google.com"))
.addTo(Address.create("ekempin", "ekempin@google.com"))
.addCc(Address.create("Dave Borowitz", "dborowitz@google.com"))
.addCc(Address.create("Jonathan Nieder", "jrn@google.com"))
.addCc(Address.create("Patrick Hiesel", "hiesel@google.com"))
.textContent(textContent)
.subject("Change in gerrit[master]: (Re)enable voting buttons for merged changes")
.dateReceived(

View File

@@ -61,8 +61,8 @@ public class AutoReplyMailFilterTest {
// Build Message
MailMessage.Builder b = MailMessage.builder();
b.id("some id");
b.from(new Address("admim@example.com"));
b.addTo(new Address("gerrit@my-company.com")); // Not evaluated
b.from(Address.create("admim@example.com"));
b.addTo(Address.create("gerrit@my-company.com")); // Not evaluated
b.subject("");
b.dateReceived(Instant.now());
b.textContent("I am currently out of office, please leave a code review after the beep.");

View File

@@ -85,8 +85,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name);
assertThat(r.getEmail()).isEqualTo(email);
assertThat(r.name()).isEqualTo(name);
assertThat(r.email()).isEqualTo(email);
verifyAccountCacheGet(user);
}
@@ -99,8 +99,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isNull();
assertThat(r.getEmail()).isEqualTo(email);
assertThat(r.name()).isNull();
assertThat(r.email()).isEqualTo(email);
verifyAccountCacheGet(user);
}
@@ -113,8 +113,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name + " (Code Review)");
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(name + " (Code Review)");
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyAccountCacheGet(user);
}
@@ -123,8 +123,8 @@ public class FromAddressGeneratorProviderTest {
setFrom("USER");
final Address r = create().from(null);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(ident.getName());
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(ident.getName());
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyZeroInteractions(accountCache);
}
@@ -138,8 +138,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name);
assertThat(r.getEmail()).isEqualTo(email);
assertThat(r.name()).isEqualTo(name);
assertThat(r.email()).isEqualTo(email);
verifyAccountCacheGet(user);
}
@@ -153,8 +153,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name + " (Code Review)");
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(name + " (Code Review)");
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyAccountCacheGet(user);
}
@@ -169,8 +169,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name);
assertThat(r.getEmail()).isEqualTo(email);
assertThat(r.name()).isEqualTo(name);
assertThat(r.email()).isEqualTo(email);
verifyAccountCacheGet(user);
}
@@ -185,8 +185,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name + " (Code Review)");
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(name + " (Code Review)");
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyAccountCacheGet(user);
}
@@ -200,8 +200,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name);
assertThat(r.getEmail()).isEqualTo(email);
assertThat(r.name()).isEqualTo(name);
assertThat(r.email()).isEqualTo(email);
verifyAccountCacheGet(user);
}
@@ -227,8 +227,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(ident.getName());
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(ident.getName());
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyZeroInteractions(accountCache);
}
@@ -237,8 +237,8 @@ public class FromAddressGeneratorProviderTest {
setFrom("SERVER");
final Address r = create().from(null);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(ident.getName());
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(ident.getName());
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyZeroInteractions(accountCache);
}
@@ -264,8 +264,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name + " (Code Review)");
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(name + " (Code Review)");
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyAccountCacheGet(user);
}
@@ -278,8 +278,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo("Anonymous Coward (Code Review)");
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo("Anonymous Coward (Code Review)");
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyAccountCacheGet(user);
}
@@ -292,8 +292,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(name + " (Code Review)");
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(name + " (Code Review)");
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyAccountCacheGet(user);
}
@@ -302,8 +302,8 @@ public class FromAddressGeneratorProviderTest {
setFrom("MIXED");
final Address r = create().from(null);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(ident.getName());
assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
assertThat(r.name()).isEqualTo(ident.getName());
assertThat(r.email()).isEqualTo(ident.getEmailAddress());
verifyZeroInteractions(accountCache);
}
@@ -317,8 +317,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo("A " + name + " B");
assertThat(r.getEmail()).isEqualTo("my.server@email.address");
assertThat(r.name()).isEqualTo("A " + name + " B");
assertThat(r.email()).isEqualTo("my.server@email.address");
verifyAccountCacheGet(user);
}
@@ -331,8 +331,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(user);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo("A Anonymous Coward B");
assertThat(r.getEmail()).isEqualTo("my.server@email.address");
assertThat(r.name()).isEqualTo("A Anonymous Coward B");
assertThat(r.email()).isEqualTo("my.server@email.address");
}
@Test
@@ -341,8 +341,8 @@ public class FromAddressGeneratorProviderTest {
final Address r = create().from(null);
assertThat(r).isNotNull();
assertThat(r.getName()).isEqualTo(ident.getName());
assertThat(r.getEmail()).isEqualTo("my.server@email.address");
assertThat(r.name()).isEqualTo(ident.getName());
assertThat(r.email()).isEqualTo("my.server@email.address");
}
private Account.Id user(String name, String email) {

View File

@@ -431,11 +431,11 @@ public class ChangeNotesStateTest {
ImmutableTable.<ReviewerStateInternal, Address, Timestamp>builder()
.put(
ReviewerStateInternal.CC,
new Address("Name1", "email1@example.com"),
Address.create("Name1", "email1@example.com"),
new Timestamp(1212L))
.put(
ReviewerStateInternal.REVIEWER,
new Address("Name2", "email2@example.com"),
Address.create("Name2", "email2@example.com"),
new Timestamp(3434L))
.build()))
.build(),
@@ -465,7 +465,7 @@ public class ChangeNotesStateTest {
ReviewerByEmailSet.fromTable(
ImmutableTable.of(
ReviewerStateInternal.CC,
new Address("emailonly@example.com"),
Address.create("emailonly@example.com"),
new Timestamp(1212L))))
.build(),
ChangeNotesStateProto.newBuilder()
@@ -484,8 +484,8 @@ public class ChangeNotesStateTest {
ImmutableSet<Address> ccs = actual.reviewersByEmail().byState(ReviewerStateInternal.CC);
assertThat(ccs).hasSize(1);
Address address = Iterables.getOnlyElement(ccs);
assertThat(address.getName()).isNull();
assertThat(address.getEmail()).isEqualTo("emailonly@example.com");
assertThat(address.name()).isNull();
assertThat(address.email()).isEqualTo("emailonly@example.com");
}
@Test
@@ -525,11 +525,11 @@ public class ChangeNotesStateTest {
ImmutableTable.<ReviewerStateInternal, Address, Timestamp>builder()
.put(
ReviewerStateInternal.CC,
new Address("Name1", "email1@example.com"),
Address.create("Name1", "email1@example.com"),
new Timestamp(1212L))
.put(
ReviewerStateInternal.REVIEWER,
new Address("Name2", "email2@example.com"),
Address.create("Name2", "email2@example.com"),
new Timestamp(3434L))
.build()))
.build(),

View File

@@ -2920,7 +2920,7 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
@Test
public void putReviewerByEmail() throws Exception {
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2933,7 +2933,7 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
@Test
public void putAndRemoveReviewerByEmail() throws Exception {
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2950,7 +2950,7 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
@Test
public void putRemoveAndAddBackReviewerByEmail() throws Exception {
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2971,8 +2971,8 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
@Test
public void putReviewerByEmailAndCcByEmail() throws Exception {
Address adrReviewer = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
Address adrCc = new Address("Foo Bor", "foo.bar.2@gerritcodereview.com");
Address adrReviewer = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
Address adrCc = Address.create("Foo Bor", "foo.bar.2@gerritcodereview.com");
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2993,7 +2993,7 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
@Test
public void putReviewerByEmailAndChangeToCc() throws Exception {
Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
@@ -3049,8 +3049,8 @@ public class ChangeNotesTest extends AbstractChangeNotesTest {
@Test
public void pendingReviewers() throws Exception {
Address adr1 = new Address("Foo Bar1", "foo.bar1@gerritcodereview.com");
Address adr2 = new Address("Foo Bar2", "foo.bar2@gerritcodereview.com");
Address adr1 = Address.create("Foo Bar1", "foo.bar1@gerritcodereview.com");
Address adr2 = Address.create("Foo Bar2", "foo.bar2@gerritcodereview.com");
Account.Id ownerId = changeOwner.getAccount().id();
Account.Id otherUserId = otherUser.getAccount().id();

View File

@@ -388,7 +388,7 @@ public class CommitMessageOutputTest extends AbstractChangeNotesTest {
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
update.putReviewerByEmail(
new Address("John Doe", "j.doe@gerritcodereview.com"), ReviewerStateInternal.REVIEWER);
Address.create("John Doe", "j.doe@gerritcodereview.com"), ReviewerStateInternal.REVIEWER);
update.commit();
assertBodyEquals(
@@ -401,7 +401,8 @@ public class CommitMessageOutputTest extends AbstractChangeNotesTest {
public void ccByEmail() throws Exception {
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
update.putReviewerByEmail(new Address("j.doe@gerritcodereview.com"), ReviewerStateInternal.CC);
update.putReviewerByEmail(
Address.create("j.doe@gerritcodereview.com"), ReviewerStateInternal.CC);
update.commit();
assertBodyEquals(