Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: unit tests #27

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions dist/java/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id 'java-library'
id "com.vanniktech.maven.publish.base" version "0.30.0"
id 'com.google.osdetector' version '1.7.3'
alias libs.plugins.maven.publish
alias libs.plugins.osdetector
}

group = 'mp.code'
Expand Down Expand Up @@ -107,11 +107,18 @@ repositories {

sourceSets {
main.java.srcDirs = ['src/']
test.java.srcDirs = ['src-test/']
}

dependencies {
compileOnly 'org.projectlombok:lombok:1.18.34'
annotationProcessor 'org.projectlombok:lombok:1.18.34'
compileOnly libs.lombok
annotationProcessor libs.lombok
testImplementation libs.junit.jupiter
testImplementation(platform(libs.junit.bom))
}

test {
useJUnitPlatform()
}

tasks.register('cargoBuild', Exec) {
Expand Down Expand Up @@ -156,7 +163,7 @@ import com.vanniktech.maven.publish.SonatypeHost
mavenPublishing {
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL, true)
signAllPublications()
coordinates(project.group, rootProject.name, project.version)
coordinates(project.group as String, rootProject.name, project.version as String)

pom {
name = rootProject.name
Expand All @@ -183,3 +190,6 @@ mavenPublishing {
}
}
}

// useful for debugging
test.doFirst { environment 'RUST_BACKTRACE', 'full' }
14 changes: 14 additions & 0 deletions dist/java/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[versions]
lombok = '1.18.34'
junit = '5.11.0'
maven-publish = '0.30.0'
osdetector = '1.7.3'

[plugins]
maven-publish = { id = 'com.vanniktech.maven.publish.base', version.ref = 'maven-publish' }
osdetector = { id = 'com.google.osdetector', version.ref = 'osdetector' }

[libraries]
lombok = { group = 'org.projectlombok', name = 'lombok', version.ref = 'lombok' }
junit-jupiter = { group = 'org.junit.jupiter', name = 'junit-jupiter', version.ref = 'junit' }
junit-bom = { group = 'org.junit', name = 'junit-bom', version.ref = 'junit' }
8 changes: 8 additions & 0 deletions dist/java/settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
rootProject.name = 'codemp'
dependencyResolutionManagement {
versionCatalogs {
libs {
from(files('libs.versions.toml'))
}
}
}

226 changes: 226 additions & 0 deletions dist/java/src-test/CodeMPTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import mp.code.*;
import mp.code.data.Config;
import mp.code.data.Cursor;
import mp.code.data.TextChange;
import mp.code.data.User;
import mp.code.exceptions.ConnectionException;
import mp.code.exceptions.ConnectionRemoteException;
import mp.code.exceptions.ControllerException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Objects;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.UUID;

import static mp.code.data.DetachResult.DETACHING;

@SuppressWarnings({"StatementWithEmptyBody", "OptionalGetWithoutIsPresent"})
public class CodeMPTest {
private final Client client;
private final Client otherClient;

// client connection init
public CodeMPTest() throws ConnectionException {
new Thread(() -> Extensions.drive(true)); // drive thread so callback works
//Extensions.setupTracing(null, true);

this.client = Client.connect(new Config(
Objects.requireNonNull(System.getenv("CODEMP_TEST_USERNAME_1")),
Objects.requireNonNull(System.getenv("CODEMP_TEST_PASSWORD_1")),
"api.codemp.dev",
50053,
false
));

// failed tests may have cluttered the list, clean it first
for(String ws : this.client.listWorkspaces(true, false)) {
this.client.deleteWorkspace(ws);
}

this.otherClient = Client.connect(new Config(
Objects.requireNonNull(System.getenv("CODEMP_TEST_USERNAME_2")),
Objects.requireNonNull(System.getenv("CODEMP_TEST_PASSWORD_2")),
"api.code.mp",
50053,
false
));
}

@Test
void testGetUser() {
User u = this.client.getUser();
//assert u.name.equals(System.getenv("CODEMP_TEST_USERNAME_1"));
//assert u.id.toString().equals(System.getenv("CODEMP_TEST_ID_1"));
}

@Test
void testWorkspaceInteractions() throws ConnectionException {
String randomName = UUID.randomUUID().toString();

int oldOwned = this.client.listWorkspaces(true, false).length;
int oldInvited = this.client.listWorkspaces(false, true).length;
this.client.createWorkspace(randomName);
assert (oldOwned + 1) == this.client.listWorkspaces(true, false).length;
assert oldInvited == this.client.listWorkspaces(false, true).length;

int activeWorkspaces = this.client.activeWorkspaces().length;
this.client.joinWorkspace(randomName);
assert (activeWorkspaces + 1) == this.client.activeWorkspaces().length;

Optional<Workspace> ws = this.client.getWorkspace(randomName);
assert ws.isPresent();
assert ws.get().getWorkspaceId().equals(randomName);
ws.get().fetchBuffers();
ws.get().fetchUsers();

this.client.inviteToWorkspace(randomName, this.otherClient.getUser().name);
assert this.client.leaveWorkspace(randomName);
assert !this.otherClient.leaveWorkspace(randomName);

this.client.deleteWorkspace(randomName);
}

@Test
void testRefresh() throws ConnectionRemoteException {
this.client.refresh();
}

@Test
void testBufferInteractions() throws ConnectionException, ControllerException, InterruptedException {
String randomWorkspace = UUID.randomUUID().toString();
String randomBuffer = UUID.randomUUID().toString();

// prepare first client
this.client.createWorkspace(randomWorkspace);
Workspace ws = this.client.joinWorkspace(randomWorkspace);

// test buffer creation and verify that the buffer list has changed
int oldFileTree = ws.getFileTree(Optional.empty(), true).length;
ws.createBuffer(randomBuffer);
assert (oldFileTree + 1) == ws.getFileTree(Optional.empty(), true).length;

// test buffer filters
assert ws.getFileTree(Optional.of(randomBuffer.substring(0, 10)), true).length == 0;
assert ws.getFileTree(Optional.of(randomBuffer.substring(0, 10)), false).length == 1;

int oldActive = ws.activeBuffers().length;
ws.attachToBuffer(randomBuffer);
assert (oldActive + 1) == ws.activeBuffers().length;

BufferController buffer = ws.getBuffer(randomBuffer).get();

// prepare second client and clean queue
this.client.inviteToWorkspace(ws.getWorkspaceId(), this.otherClient.getUser().name);
BufferController otherBuffer = this.otherClient.joinWorkspace(randomWorkspace).attachToBuffer(randomBuffer);
while(buffer.tryRecv().isPresent()) {}

TextChange textChange = new TextChange(0, 0, "", OptionalLong.empty());

/* Testing callback */
buffer.callback(bufferController -> new Thread(() -> {
try {
assert bufferController.recv().equals(textChange);
} catch(ControllerException e) {
throw new RuntimeException(e);
}
}).start());

otherBuffer.send(textChange);
buffer.poll();
buffer.clearCallback();

otherBuffer.send(textChange);
buffer.recv();

otherBuffer.send(textChange);
buffer.poll();
assert buffer.tryRecv().isPresent();

assert buffer.tryRecv().isEmpty();

assert ws.detachFromBuffer(randomBuffer) == DETACHING;

this.otherClient.getWorkspace(randomWorkspace).get().createBuffer(UUID.randomUUID().toString());
assert ws.event().getChangedBuffer().isPresent();

ws.deleteBuffer(randomBuffer);
Assertions.assertEquals(oldFileTree, ws.getFileTree(Optional.empty(), true).length);

this.client.leaveWorkspace(randomWorkspace);
this.client.deleteWorkspace(randomWorkspace);
}

@Test
void testWorkspaceEvents() throws ConnectionException, ControllerException {
String randomWorkspace = UUID.randomUUID().toString();

// prepare first client
this.client.createWorkspace(randomWorkspace);
Workspace ws = this.client.joinWorkspace(randomWorkspace);
this.client.inviteToWorkspace(randomWorkspace, this.otherClient.getUser().name);

// prepare second client
this.otherClient.joinWorkspace(randomWorkspace).createBuffer(UUID.randomUUID().toString());

// block until event is received
assert ws.event().getChangedBuffer().isPresent();

// cleanup
this.otherClient.leaveWorkspace(randomWorkspace);
this.client.deleteWorkspace(randomWorkspace);
}

@Test
void testCursorInteractions() throws ConnectionException, ControllerException, InterruptedException {
String randomWorkspace = UUID.randomUUID().toString();
String randomBuffer = UUID.randomUUID().toString();

// prepare first client
this.client.createWorkspace(randomWorkspace);
Workspace ws = this.client.joinWorkspace(randomWorkspace);
ws.createBuffer(randomBuffer);
ws.attachToBuffer(randomBuffer);
CursorController cursor = ws.getCursor();

// prepare second client and clean queue
this.client.inviteToWorkspace(ws.getWorkspaceId(), this.otherClient.getUser().name);
CursorController otherCursor = this.otherClient.joinWorkspace(randomWorkspace).getCursor();
while(cursor.tryRecv().isPresent()) {}

Cursor someCursor = new Cursor(
0, 0, 0, 0, randomBuffer, this.otherClient.getUser().name
);

/* Testing callback */
cursor.callback(cursorController -> new Thread(() -> {
try {
assert cursorController.recv().equals(someCursor);
} catch(ControllerException e) {
throw new RuntimeException(e);
}
}).start());

otherCursor.send(someCursor);
cursor.poll(); // wait for other thread to send
cursor.clearCallback(); // should have now received the first callback, clear it

/* Testing recv and tryRecv */
otherCursor.send(someCursor);
cursor.recv(); // block until receive

// send flat cursor
otherCursor.send(new Cursor(
0, 0, 0, 0, randomBuffer, this.otherClient.getUser().name
));
cursor.poll();
assert cursor.tryRecv().isPresent(); // expect something (and consume)
assert cursor.tryRecv().isEmpty(); // expect nothing

// cleanup
this.otherClient.leaveWorkspace(randomWorkspace);
this.client.leaveWorkspace(randomWorkspace);
this.client.deleteWorkspace(randomWorkspace);
}
}