/*******************************************************************************
* Copyright (c) 2011 Arapiki Solutions Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* "Peter Smith <psmith@arapiki.com>" - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.scanner.legacy;
import static org.junit.Assert.*;
import java.io.File;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.buildml.model.IActionMgr;
import com.buildml.model.IActionMgr.OperationType;
import com.buildml.model.IBuildStore;
import com.buildml.model.IFileMgr;
import com.buildml.model.IFileMgr.PathType;
import com.buildml.utils.errors.ErrorCode;
import com.buildml.utils.os.SystemUtils;
/**
* Basic testing that the LegacyBuildScanner can produce a valid
* BuildStore. There are many test cases, split over multiple
* test case files, with this file testing C Functions that
* perform an open()-like operation.
*
* @author "Peter Smith <psmith@arapiki.com>"
*/
public class TestCFuncOpen {
/* variables used in many test cases */
private IBuildStore bs = null;
private IActionMgr actionMgr = null;
private IFileMgr fileMgr = null;
private int rootAction;
private int action;
private Integer fileAccesses[], fileReads[], fileWrites[], fileModifies[];
/** temporary directory into which test cases can store files */
private File tmpDir;
/*-------------------------------------------------------------------------------------*/
/**
* Called before each test case starts. Creates a temporary directory in which the
* test case can store temporary files.
* @throws Exception
*/
@Before
public void setUp() throws Exception {
tmpDir = SystemUtils.createTempDir();
}
/*-------------------------------------------------------------------------------------*/
/**
* Called after each test case ends. Removes the temporary directory and its content.
* @throws Exception
*/
@After
public void tearDown() throws Exception {
SystemUtils.deleteDirectory(tmpDir);
}
/*-------------------------------------------------------------------------------------*/
/**
* Given the source code of a small C program, compile the program and scan it into a
* BuildStore. We then retrieve the one (and only) action that was registered in the
* BuildStore, along with the lists of files that were accessed (accessed, read and written).
* @param programCode The body of the small C program to be compiled.
* @param args The command line arguments to pass to the small C program.
* @throws Exception Something went wrong when compiling/running the program.
*/
private void traceOneProgram(String programCode, String args[]) throws Exception {
/* compile, run, and trace the program */
bs = BuildScannersCommonTestUtils.parseLegacyProgram(tmpDir, programCode, args);
/* fetch references to sub objects */
actionMgr = bs.getActionMgr();
fileMgr = bs.getFileMgr();
/* find the root action */
rootAction = actionMgr.getRootAction("root");
/* there should only be one child action */
Integer childActions[] = actionMgr.getChildren(rootAction);
assertEquals(1, childActions.length);
/* this is the action ID of the one action */
action = childActions[0];
/* fetch the file access arrays */
fileAccesses = actionMgr.getFilesAccessed(action, OperationType.OP_UNSPECIFIED);
fileReads = actionMgr.getFilesAccessed(action, OperationType.OP_READ);
fileWrites = actionMgr.getFilesAccessed(action, OperationType.OP_WRITE);
fileModifies = actionMgr.getFilesAccessed(action, OperationType.OP_MODIFIED);
}
/*-------------------------------------------------------------------------------------*/
/**
* Common method for testing creat() and creat64().
* @param func Which function to test ("creat" or "creat64").
* @throws Exception
*/
public void testCreatCmn(String func) throws Exception {
/*
* Create a file using an absolute path.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" int fd = " + func + "(\"" + tmpDir + "/test-file1\", 0644);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
int fileId = fileMgr.getPath(tmpDir + "/test-file1");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Create a file using a relative path.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = " + func + "(\"test-file2\", 0644);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/test-file2");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the creat() C function.
* @throws Exception
*/
@Test
public void testCreat() throws Exception {
testCreatCmn("creat");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the creat64() C function.
* @throws Exception
*/
@Test
public void testCreat64() throws Exception {
testCreatCmn("creat64");
}
/*-------------------------------------------------------------------------------------*/
/**
* Common code for testing fopen() and fopen64().
* @param func The function to invoke ("fopen" or "fopen64").
* @throws Exception
*/
public void testFopenCmn(String func) throws Exception {
/*
* Open a file for read, using its absolute path name.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = " + func + "(\"/etc/passwd\", \"r\");" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
int fileId = fileMgr.getPath("/etc/passwd");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileReads[0].intValue());
assertEquals(PathType.TYPE_FILE, fileMgr.getPathType(fileReads[0].intValue()));
/*
* Open a missing file, in read mode - no read should be logged.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = " + func + "(\"/etc/not-passwd\", \"r\");" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
/*
* Open a relative path, in read mode.
*/
assertTrue(new File(tmpDir, "test-file1").createNewFile());
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" FILE *file = " + func + "(\"test-file1\", \"r\");" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/test-file1");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileReads[0].intValue());
/*
* Open a relative path, in write mode.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" FILE *file = " + func + "(\"test-file2\", \"w\");" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/test-file2");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Try opening files with a range of valid open modes.
*/
assertTrue(new File(tmpDir, "test-file-r").createNewFile());
assertTrue(new File(tmpDir, "test-file-rb").createNewFile());
assertTrue(new File(tmpDir, "test-file-r+").createNewFile());
assertTrue(new File(tmpDir, "test-file-rb+").createNewFile());
assertTrue(new File(tmpDir, "test-file-r+b").createNewFile());
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" FILE *file = " + func + "(\"test-file-r\", \"r\");" +
" file = " + func + "(\"test-file-rb\", \"rb\");" +
" file = " + func + "(\"test-file-w\", \"w\");" +
" file = " + func + "(\"test-file-wb\", \"wb\");" +
" file = " + func + "(\"test-file-a\", \"a\");" +
" file = " + func + "(\"test-file-ab\", \"ab\");" +
" file = " + func + "(\"test-file-r+\", \"r+\");" +
" file = " + func + "(\"test-file-rb+\", \"rb+\");" +
" file = " + func + "(\"test-file-r+b\", \"r+b\");" +
" file = " + func + "(\"test-file-w+\", \"w+\");" +
" file = " + func + "(\"test-file-wb+\", \"w+b\");" +
" file = " + func + "(\"test-file-a+\", \"a+\");" +
" file = " + func + "(\"test-file-ab+\", \"ab+\");" +
" file = " + func + "(\"test-file-a+b\", \"a+b\");" +
" return 0;" +
"}", null);
assertEquals(2, fileReads.length);
assertEquals(9, fileWrites.length);
assertEquals(3, fileModifies.length);
/*
* Test opening a directory.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" FILE *file = " + func + "(\".\", \"r\");" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(PathType.TYPE_DIR, fileMgr.getPathType(fileReads[0].intValue()));
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the fopen() C function.
* @throws Exception
*/
@Test
public void testFopen() throws Exception {
testFopenCmn("fopen");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the fopen64() C function.
* @throws Exception
*/
@Test
public void testFopen64() throws Exception {
testFopenCmn("fopen64");
}
/*-------------------------------------------------------------------------------------*/
/**
* Common test code for the freopen() and freopen64() functions.
* @param func The function to use ("freopen" or "freopen64").
* @throws Exception
*/
public void testFreopenCmn(String func) throws Exception {
String fileName1 = tmpDir + "/file1";
String fileName2 = tmpDir + "/file2";
assertTrue(new File(fileName1).createNewFile());
assertTrue(new File(fileName2).createNewFile());
/*
* Open a temporary file in read mode, then reopen in write mode,
* using the same file name.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = fopen(\"" + fileName1 + "\", \"r\");" +
" file = " + func + "(\"" + fileName1 + "\", \"w\", file);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(1, fileModifies.length);
int fileId = fileMgr.getPath(fileName1);
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileModifies[0].intValue());
/*
* Open a temporary file in read mode, then reopen in write mode,
* using the same file name, but using a relative path.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" FILE *file = fopen(\"" + fileName1 + "\", \"r\");" +
" file = " + func + "(\"file1\", \"w\", file);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(1, fileModifies.length);
fileId = fileMgr.getPath(fileName1);
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileModifies[0].intValue());
/*
* Open a temporary file in read mode, then reopen in write mode
* using a different file name.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = fopen(\"" + fileName1 + "\", \"r\");" +
" file = " + func + "(\"" + fileName2 + "\", \"w\", file);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(1, fileWrites.length);
assertEquals(0, fileModifies.length);
fileId = fileMgr.getPath(fileName1);
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileReads[0].intValue());
fileId = fileMgr.getPath(fileName2);
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Open a temporary file in read mode, then reopen in write mode,
* but using NULL for the file name (to reopen the same file).
* TODO: this case not yet implemented properly (see interposer
* function for an explanation). This test case validates
* the INCORRECT behaviour and should be fixed.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = fopen(\"" + fileName1 + "\", \"r\");" +
" file = " + func + "(NULL, \"w\", file);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(0, fileModifies.length);
/*
* Open a temporary file in write mode, then reopen in read mode,
* using the same file name.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = fopen(\"" + fileName1 + "\", \"w\");" +
" file = " + func + "(\"" + fileName1 + "\", \"r\", file);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
assertEquals(0, fileModifies.length);
fileId = fileMgr.getPath(fileName1);
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Open a temporary file in write mode, then reopen a different
* file which is missing.
*/
traceOneProgram(
"#include <stdio.h>\n" +
"int main() {" +
" FILE *file = fopen(\"" + fileName1 + "\", \"w\");" +
" file = " + func + "(\"missing-file\", \"r\", file);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
assertEquals(0, fileModifies.length);
fileId = fileMgr.getPath(fileName1);
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the freopen() C function.
* @throws Exception
*/
@Test
public void testFreopen() throws Exception {
testFreopenCmn("freopen");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the freopen64() C function.
* @throws Exception
*/
@Test
public void testFreopen64() throws Exception {
testFreopenCmn("freopen64");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the ftok() C function.
* @throws Exception
*/
@Test
public void testFtok() throws Exception {
/*
* Execute ftok() on a legitimate file.
*/
traceOneProgram(
"#include <sys/ipc.h>\n" +
"int main() {" +
" key_t key = ftok(\"/etc/passwd\", 10);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
int fileId = fileMgr.getPath("/etc/passwd");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileReads[0].intValue());
assertEquals(PathType.TYPE_FILE, fileMgr.getPathType(fileReads[0].intValue()));
/*
* Execute ftok() on a missing file.
*/
traceOneProgram(
"#include <sys/ipc.h>\n" +
"int main() {" +
" key_t key = ftok(\"/missing-file\", 10);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
}
/*-------------------------------------------------------------------------------------*/
/**
* Common code for testing the open() and open64() functions.
* @param func The function to invoke ("open" or "open64").
* @throws Exception
*/
public void testOpenCmn(String func) throws Exception {
/*
* Open a file with an absolute path, in read-mode.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" int fd = " + func + "(\"/etc/passwd\", O_RDONLY);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
int fileId = fileMgr.getPath("/etc/passwd");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileReads[0].intValue());
assertEquals(PathType.TYPE_FILE, fileMgr.getPathType(fileReads[0].intValue()));
/*
* Open a file with a relative path, in read-mode.
*/
assertTrue(new File(tmpDir, "test-file1").createNewFile());
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = " + func + "(\"test-file1\", O_RDONLY);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/test-file1");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileReads[0].intValue());
/*
* Open a file with a relative path, in write-mode.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = " + func + "(\"test-file2\", O_CREAT | O_WRONLY);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/test-file2");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Open a file with a relative path, in modify-mode.
*/
assertTrue(new File(tmpDir, "test-file3").createNewFile());
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = " + func + "(\"test-file3\", O_RDWR);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(1, fileModifies.length);
fileId = fileMgr.getPath(tmpDir + "/test-file3");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileModifies[0].intValue());
/*
* Open a file that doesn't exist.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = open(\"test-file-missing\", O_RDWR);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(0, fileModifies.length);
/*
* Open a directory.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = open(\".\", O_RDONLY);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(0, fileModifies.length);
assertEquals(PathType.TYPE_DIR, fileMgr.getPathType(fileReads[0].intValue()));
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the open() C function.
* @throws Exception
*/
@Test
public void testOpen() throws Exception {
testOpenCmn("open");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the open64() C function.
* @throws Exception
*/
@Test
public void testOpen64() throws Exception {
testOpenCmn("open64");
}
/*-------------------------------------------------------------------------------------*/
/**
* Command method for testing openat() and openat64().
* @param func The function to test ("openat" or "openat64").
* @throws Exception
*/
public void testOpenatCmn(String func) throws Exception {
/*
* Test openat() with a path that's relative to a valid directory fd.
*/
assertTrue(new File(tmpDir, "sub-dir").mkdirs());
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int dirfd = open(\"sub-dir\", O_RDONLY);" +
" int fd = " + func + "(dirfd, \"test-file1\", O_CREAT|O_WRONLY, 0666);" +
" close(dirfd);" +
" close(fd);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length); /* the sub-dir directory is read */
assertEquals(1, fileWrites.length);
int fileId = fileMgr.getPath(tmpDir + "/sub-dir/test-file1");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Test openat() with an absolute path name (a dirfd is provided, but shouldn't be used).
*/
assertTrue(new File(tmpDir, "sub-dir2").mkdirs());
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int dirfd = open(\"sub-dir\", O_RDONLY);" +
" int fd = " + func + "(dirfd, \"" + tmpDir + "/sub-dir2/test-file2\"," +
"O_CREAT|O_WRONLY, 0666);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length); /* the sub-dir directory is read */
assertEquals(1, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/sub-dir2/test-file2");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Test openat() with a path relative to the current directory.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = " + func + "(AT_FDCWD, \"sub-dir/test-file3\"," +
"O_CREAT|O_WRONLY, 0666);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(1, fileWrites.length);
fileId = fileMgr.getPath(tmpDir + "/sub-dir/test-file3");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileWrites[0].intValue());
/*
* Test openat() with an invalid dirfd number - should fail.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int fd = " + func + "(100, \"sub-dir/test-file4\"," +
"O_CREAT|O_WRONLY, 0666);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
/*
* Test openat() with a file that doesn't exist - should fail.
*/
traceOneProgram(
"#include <fcntl.h>\n" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int dirfd = open(\"sub-dir\", O_RDONLY);" +
" int fd = " + func + "(dirfd, \"sub-dir/test-file-missing\"," +
"O_RDONLY, 0666);" +
" return 0;" +
"}", null);
assertEquals(1, fileReads.length); /* the sub-dir directory is read */
assertEquals(0, fileWrites.length);
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the openat() C function.
* @throws Exception
*/
@Test
public void testOpenat() throws Exception {
testOpenatCmn("openat");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the openat64() C function.
* @throws Exception
*/
@Test
public void testOpenat64() throws Exception {
testOpenatCmn("openat64");
}
/*-------------------------------------------------------------------------------------*/
/**
* Common code for testing truncate() and truncate64().
* @param func Function to use ("truncate" or "truncate64").
* @throws Exception
*/
public void testTruncateCmn(String func) throws Exception {
/*
* Truncate a file using an absolute path. Note that we
* need an explicit declaration of truncate64(), since it
* expects a 64-bit offset value.
*/
assertTrue(new File(tmpDir, "test-file1").createNewFile());
traceOneProgram(
"#include <stdio.h>\n" +
"#include <unistd.h>\n" +
"extern int truncate64(const char *, __off64_t);" +
"int main() {" +
" int status = " + func + "(\"" + tmpDir + "/test-file1\", 10);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(1, fileModifies.length);
int fileId = fileMgr.getPath(tmpDir + "/test-file1");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileModifies[0].intValue());
/*
* Truncate a file using a relative path.
*/
assertTrue(new File(tmpDir, "test-file2").createNewFile());
traceOneProgram(
"#include <stdio.h>\n" +
"#include <unistd.h>\n" +
"extern int truncate64(const char *, __off64_t);" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int status = " + func + "(\"test-file2\", 10);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(1, fileModifies.length);
fileId = fileMgr.getPath(tmpDir + "/test-file2");
assertNotSame(ErrorCode.NOT_FOUND, fileId);
assertEquals(fileId, fileModifies[0].intValue());
/*
* Truncate a non-existent file
*/
traceOneProgram(
"#include <stdio.h>\n" +
"#include <unistd.h>\n" +
"extern int truncate64(const char *, __off64_t);" +
"int main() {" +
" chdir(\"" + tmpDir + "\");" +
" int status = " + func + "(\"test-file-missing\", 10);" +
" return 0;" +
"}", null);
assertEquals(0, fileReads.length);
assertEquals(0, fileWrites.length);
assertEquals(0, fileModifies.length);
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the truncate() C function.
* @throws Exception
*/
@Test
public void testTruncate() throws Exception {
testTruncateCmn("truncate");
}
/*-------------------------------------------------------------------------------------*/
/**
* Test the truncate64() C function.
* @throws Exception
*/
@Test
public void testTruncate64() throws Exception {
testTruncateCmn("truncate64");
}
/*-------------------------------------------------------------------------------------*/
}