public Status upload(String localFilePath, String remoteFilePath) {
        // Preconditions.checkArgument(remoteFilePath.startsWith(location), remoteFilePath);
        // get md5usm of local file
        File file = new File(localFilePath);
        String md5sum;
        try {
            md5sum = DigestUtils.md5Hex(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            return new Status(ErrCode.NOT_FOUND, "file " + localFilePath + " does not exist");
        } catch (IOException e) {
            return new Status(ErrCode.COMMON_ERROR, "failed to get md5sum of file: " + localFilePath);
        }
        Preconditions.checkState(!Strings.isNullOrEmpty(md5sum));
        String tmpRemotePath = assembleFileNameWithSuffix(remoteFilePath, SUFFIX_TMP_FILE);
        String finalRemotePath = assembleFileNameWithSuffix(remoteFilePath, md5sum);
        LOG.debug("get md5sum of file: {}. tmp remote path: {}. final remote path: {}", localFilePath, tmpRemotePath,
                finalRemotePath);

        // this may be a retry, so we should first delete remote file
        Status st = storage.delete(tmpRemotePath);
        if (!st.ok()) {
            return st;
        }

        st = storage.delete(finalRemotePath);
        if (!st.ok()) {
            return st;
        }

        // upload tmp file
        st = storage.upload(localFilePath, tmpRemotePath);
        if (!st.ok()) {
            return st;
        }

        // rename tmp file with checksum named file
        st = storage.rename(tmpRemotePath, finalRemotePath);
        if (!st.ok()) {
            return st;
        }
        LOG.info("finished to upload local file {} to remote file: {}", localFilePath, finalRemotePath);
        return st;
    }
@Test
    public void testUpload() {
        new Expectations() {
            {
                storage.upload(anyString, anyString);
                minTimes = 0;
                result = Status.OK;

                storage.rename(anyString, anyString);
                minTimes = 0;
                result = Status.OK;

                storage.delete(anyString);
                minTimes = 0;
                result = Status.OK;
            }
        };

        repo = new Repository(10000, "repo", false, location, storage);
        String localFilePath = "./tmp_" + System.currentTimeMillis();
        try (PrintWriter out = new PrintWriter(localFilePath)) {
            out.print("a");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Assert.fail();
        }
        try {
            String remoteFilePath = location + "/remote_file";
            Status st = repo.upload(localFilePath, remoteFilePath);
            Assert.assertTrue(st.ok());
        } finally {
            File file = new File(localFilePath);
            file.delete();
        }
    }