<commit_before>package peergos.server.tests;

import org.junit.*;
import peergos.server.storage.ResetableFileInputStream;
import peergos.server.util.Args;
import peergos.server.util.PeergosNetworkUtils;
import peergos.shared.crypto.hash.*;
import peergos.shared.fingerprint.*;
import peergos.shared.util.TriFunction;
import peergos.shared.*;
import peergos.shared.cbor.*;
import peergos.shared.crypto.*;
import peergos.shared.crypto.symmetric.*;
import peergos.server.*;
import peergos.shared.social.*;
import peergos.shared.user.*;
import peergos.shared.user.fs.*;
import peergos.shared.user.fs.cryptree.*;
import peergos.shared.util.*;

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.*;

import static org.junit.Assert.assertTrue;
import static peergos.server.util.PeergosNetworkUtils.ensureSignedUp;
import static peergos.server.util.PeergosNetworkUtils.getUserContextsForNode;

public class MultiUserTests {

    private static Args args = UserTests.buildArgs();
    private Random random = new Random();
    private final NetworkAccess network;
    private static final Crypto crypto = Crypto.initJava();
    private final int userCount;

    public MultiUserTests() throws Exception {
        this.userCount = 2;
        this.network = NetworkAccess.buildJava(new URL("http://localhost:" + args.getInt("port"))).get();
    }

    @BeforeClass
    public static void init() {
        Main.PKI_INIT.main(args);
    }

    private List<UserContext> getUserContexts(int size, List<String> passwords) {
        return getUserContextsForNode(network, random, size, passwords);
    }

    @Test
    public void grantAndRevokeFileReadAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeFileReadAccess(network, network, userCount, random);
    }

    @Test
    public void grantAndRevokeFileWriteAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeFileWriteAccess(network, network, userCount, random);
    }

    @Test
    public void grantAndRevokeDirReadAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeDirReadAccess(network, network, 2, random);
    }

    @Test
    public void grantAndRevokeDirWriteAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeDirWriteAccess(network, network, 2, random);
    }

    @Test
    public void safeCopyOfFriendsReadAccess() throws Exception {
        TriFunction<UserContext, UserContext, String, CompletableFuture<Boolean>> readAccessSharingFunction =
                (u1, u2, filename) ->
        u1.shareReadAccessWith(Paths.get(u1.username, filename), Collections.singleton(u2.username));
        safeCopyOfFriends(readAccessSharingFunction);
    }

    @Test
    public void safeCopyOfFriendsWriteAccess() throws Exception {
        TriFunction<UserContext, UserContext, String, CompletableFuture<Boolean>> writeAccessSharingFunction =
                (u1, u2, filename) ->
                        u1.shareWriteAccessWith(Paths.get(u1.username, filename), Collections.singleton(u2.username));
        safeCopyOfFriends(writeAccessSharingFunction);
    }

    private void safeCopyOfFriends(TriFunction<UserContext, UserContext, String, CompletableFuture<Boolean>> sharingFunction) throws Exception {
        UserContext u1 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u2 = PeergosNetworkUtils.ensureSignedUp(random(), "b", network.clear(), crypto);

        // send follow requests from each other user to "a"
        u2.sendFollowRequest(u1.username, SymmetricKey.random()).get();

        // make "a" reciprocate all the follow requests
        List<FollowRequestWithCipherText> u1Requests = u1.processFollowRequests().get();
        for (FollowRequestWithCipherText u1Request : u1Requests) {
            boolean accept = true;
            boolean reciprocate = true;
            u1.sendReplyFollowRequest(u1Request, accept, reciprocate).get();
        }

        // complete the friendship connection
        u2.processFollowRequests().get();//needed for side effect

        // upload a file to "a"'s space
        FileWrapper u1Root = u1.getUserRoot().get();
        String filename = "somefile.txt";
        byte[] data = UserTests.randomData(10*1024*1024);

        FileWrapper uploaded = u1Root.uploadOrOverwriteFile(filename, new AsyncReader.ArrayBacked(data), data.length,
                u1.network, crypto, l -> {}, crypto.random.randomBytes(32)).get();

        // share the file from "a" to each of the others
        FileWrapper u1File = u1.getByPath(u1.username + "/" + filename).get().get();
        sharingFunction.apply(u1, u2, filename).get();

        // check other user can read the file
        FileWrapper sharedFile = u2.getByPath(u1.username + "/" + filename).get().get();
        String dirname = "adir";
        u2.getUserRoot().get().mkdir(dirname, network, false, crypto).get();
        FileWrapper targetDir = u2.getByPath(Paths.get(u2.username, dirname).toString()).get().get();

        // copy the friend's file to our own space, this should reupload the file encrypted with a new key
        // this prevents us exposing to the network our social graph by the fact that we pin the same file fragments
        sharedFile.copyTo(targetDir, u2).get();
        FileWrapper copy = u2.getByPath(Paths.get(u2.username, dirname, filename).toString()).get().get();

        // check that the copied file has the correct contents
        UserTests.checkFileContents(data, copy, u2);
        Assert.assertTrue("Different base key", ! copy.getPointer().capability.rBaseKey.equals(u1File.getPointer().capability.rBaseKey));
        Assert.assertTrue("Different metadata key", ! UserTests.getMetaKey(copy).equals(UserTests.getMetaKey(u1File)));
        Assert.assertTrue("Different data key", ! UserTests.getDataKey(copy).equals(UserTests.getDataKey(u1File)));
    }

    @Test
    public void writeAccessVariation() {

        UserContext u1 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u2 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u3 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u4 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);

        List<UserContext> all = Arrays.asList(u1, u2, u3, u4);

        // send follow requests from u1 to others
        for (int i=1; i < all.size(); i++) {
            UserContext target = all.get(i);
            u1.sendFollowRequest(target.username, SymmetricKey.random()).join();

            // make others reciprocate the follow request
            List<FollowRequestWithCipherText> u1Requests = target.processFollowRequests().join();
            for (FollowRequestWithCipherText u1Request : u1Requests) {<commit_msg>rename test<commit_after>package peergos.server.tests;

import org.junit.*;
import peergos.server.storage.ResetableFileInputStream;
import peergos.server.util.Args;
import peergos.server.util.PeergosNetworkUtils;
import peergos.shared.crypto.hash.*;
import peergos.shared.fingerprint.*;
import peergos.shared.util.TriFunction;
import peergos.shared.*;
import peergos.shared.cbor.*;
import peergos.shared.crypto.*;
import peergos.shared.crypto.symmetric.*;
import peergos.server.*;
import peergos.shared.social.*;
import peergos.shared.user.*;
import peergos.shared.user.fs.*;
import peergos.shared.user.fs.cryptree.*;
import peergos.shared.util.*;

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.*;

import static org.junit.Assert.assertTrue;
import static peergos.server.util.PeergosNetworkUtils.ensureSignedUp;
import static peergos.server.util.PeergosNetworkUtils.getUserContextsForNode;

public class MultiUserTests {

    private static Args args = UserTests.buildArgs();
    private Random random = new Random();
    private final NetworkAccess network;
    private static final Crypto crypto = Crypto.initJava();
    private final int userCount;

    public MultiUserTests() throws Exception {
        this.userCount = 2;
        this.network = NetworkAccess.buildJava(new URL("http://localhost:" + args.getInt("port"))).get();
    }

    @BeforeClass
    public static void init() {
        Main.PKI_INIT.main(args);
    }

    private List<UserContext> getUserContexts(int size, List<String> passwords) {
        return getUserContextsForNode(network, random, size, passwords);
    }

    @Test
    public void grantAndRevokeFileReadAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeFileReadAccess(network, network, userCount, random);
    }

    @Test
    public void grantAndRevokeFileWriteAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeFileWriteAccess(network, network, userCount, random);
    }

    @Test
    public void grantAndRevokeDirReadAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeDirReadAccess(network, network, 2, random);
    }

    @Test
    public void grantAndRevokeDirWriteAccess() throws Exception {
        PeergosNetworkUtils.grantAndRevokeDirWriteAccess(network, network, 2, random);
    }

    @Test
    public void safeCopyOfFriendsReadAccess() throws Exception {
        TriFunction<UserContext, UserContext, String, CompletableFuture<Boolean>> readAccessSharingFunction =
                (u1, u2, filename) ->
        u1.shareReadAccessWith(Paths.get(u1.username, filename), Collections.singleton(u2.username));
        safeCopyOfFriends(readAccessSharingFunction);
    }

    @Test
    public void safeCopyOfFriendsWriteAccess() throws Exception {
        TriFunction<UserContext, UserContext, String, CompletableFuture<Boolean>> writeAccessSharingFunction =
                (u1, u2, filename) ->
                        u1.shareWriteAccessWith(Paths.get(u1.username, filename), Collections.singleton(u2.username));
        safeCopyOfFriends(writeAccessSharingFunction);
    }

    private void safeCopyOfFriends(TriFunction<UserContext, UserContext, String, CompletableFuture<Boolean>> sharingFunction) throws Exception {
        UserContext u1 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u2 = PeergosNetworkUtils.ensureSignedUp(random(), "b", network.clear(), crypto);

        // send follow requests from each other user to "a"
        u2.sendFollowRequest(u1.username, SymmetricKey.random()).get();

        // make "a" reciprocate all the follow requests
        List<FollowRequestWithCipherText> u1Requests = u1.processFollowRequests().get();
        for (FollowRequestWithCipherText u1Request : u1Requests) {
            boolean accept = true;
            boolean reciprocate = true;
            u1.sendReplyFollowRequest(u1Request, accept, reciprocate).get();
        }

        // complete the friendship connection
        u2.processFollowRequests().get();//needed for side effect

        // upload a file to "a"'s space
        FileWrapper u1Root = u1.getUserRoot().get();
        String filename = "somefile.txt";
        byte[] data = UserTests.randomData(10*1024*1024);

        FileWrapper uploaded = u1Root.uploadOrOverwriteFile(filename, new AsyncReader.ArrayBacked(data), data.length,
                u1.network, crypto, l -> {}, crypto.random.randomBytes(32)).get();

        // share the file from "a" to each of the others
        FileWrapper u1File = u1.getByPath(u1.username + "/" + filename).get().get();
        sharingFunction.apply(u1, u2, filename).get();

        // check other user can read the file
        FileWrapper sharedFile = u2.getByPath(u1.username + "/" + filename).get().get();
        String dirname = "adir";
        u2.getUserRoot().get().mkdir(dirname, network, false, crypto).get();
        FileWrapper targetDir = u2.getByPath(Paths.get(u2.username, dirname).toString()).get().get();

        // copy the friend's file to our own space, this should reupload the file encrypted with a new key
        // this prevents us exposing to the network our social graph by the fact that we pin the same file fragments
        sharedFile.copyTo(targetDir, u2).get();
        FileWrapper copy = u2.getByPath(Paths.get(u2.username, dirname, filename).toString()).get().get();

        // check that the copied file has the correct contents
        UserTests.checkFileContents(data, copy, u2);
        Assert.assertTrue("Different base key", ! copy.getPointer().capability.rBaseKey.equals(u1File.getPointer().capability.rBaseKey));
        Assert.assertTrue("Different metadata key", ! UserTests.getMetaKey(copy).equals(UserTests.getMetaKey(u1File)));
        Assert.assertTrue("Different data key", ! UserTests.getDataKey(copy).equals(UserTests.getDataKey(u1File)));
    }

    @Test
    public void revokeReadAccessToWritableFile() {

        UserContext u1 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u2 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u3 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);
        UserContext u4 = PeergosNetworkUtils.ensureSignedUp(random(), "a", network.clear(), crypto);

        List<UserContext> all = Arrays.asList(u1, u2, u3, u4);

        // send follow requests from u1 to others
        for (int i=1; i < all.size(); i++) {
            UserContext target = all.get(i);
            u1.sendFollowRequest(target.username, SymmetricKey.random()).join();

            // make others reciprocate the follow request
            List<FollowRequestWithCipherText> u1Requests = target.processFollowRequests().join();
            for (FollowRequestWithCipherText u1Request : u1Requests) {
{'fraction_non_alphanumeric': 0.11237410071942446, 'fraction_numerical': 0.010215827338129497, 'mean_word_length': 3.6305796135909394, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3823476', 'n_tokens_mistral': 3972, 'n_tokens_neox': 3876, 'n_words': 897}