Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins
提交
41fbaeeb
J
jenkins
项目概览
LinuxSuRen
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
41fbaeeb
编写于
12月 17, 2018
作者:
M
Matt Sicker
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Break up testForceRemoveRecursive_LockedFiles into logical tests
Signed-off-by:
N
Matt Sicker
<
boards@gmail.com
>
上级
cc809df4
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
94 addition
and
86 deletion
+94
-86
core/src/test/java/jenkins/util/io/FileLocker.java
core/src/test/java/jenkins/util/io/FileLocker.java
+1
-2
core/src/test/java/jenkins/util/io/PathRemoverTest.java
core/src/test/java/jenkins/util/io/PathRemoverTest.java
+93
-84
未找到文件。
core/src/test/java/jenkins/util/io/FileLocker.java
浏览文件 @
41fbaeeb
...
...
@@ -44,12 +44,11 @@ import static org.junit.Assert.assertTrue;
public
class
FileLocker
implements
AutoCloseable
{
private
final
Map
<
File
,
AutoCloseable
>
locks
=
new
HashMap
<>();
public
synchronized
AutoCloseable
acquireLock
(
File
file
)
throws
IOException
{
public
synchronized
void
acquireLock
(
File
file
)
throws
IOException
{
assertTrue
(
Functions
.
isWindows
());
assertThat
(
file
+
" is already locked."
,
locks
,
not
(
hasKey
(
file
)));
AutoCloseable
lock
=
new
FileInputStream
(
file
);
locks
.
put
(
file
,
lock
);
return
lock
;
}
public
synchronized
void
releaseLock
(
File
file
)
throws
Exception
{
...
...
core/src/test/java/jenkins/util/io/PathRemoverTest.java
浏览文件 @
41fbaeeb
...
...
@@ -164,7 +164,7 @@ public class PathRemoverTest {
}
@Test
public
void
testForceRemoveRecursive_LockedFiles
()
throws
Exception
{
public
void
testForceRemoveRecursive_
DeletesAsMuchAsPossibleWith
LockedFiles
()
throws
Exception
{
assumeTrue
(
Functions
.
isWindows
());
File
dir
=
tmp
.
newFolder
();
File
d1
=
new
File
(
dir
,
"d1"
);
...
...
@@ -176,97 +176,106 @@ public class PathRemoverTest {
touchWithFileName
(
f1
,
d1f1
,
d2f2
);
try
(
FileLocker
locker
=
new
FileLocker
())
{
// Test: If we cannot delete a file, we throw
// but still deletes everything it can
// even if we are not retrying deletes.
try
(
AutoCloseable
ignored
=
locker
.
acquireLock
(
d1f1
))
{
PathRemover
remover
=
PathRemover
.
newSimpleRemover
();
expectedException
.
expectMessage
(
containsString
(
dir
.
getPath
()));
remover
.
forceRemoveRecursive
(
dir
.
toPath
());
assertTrue
(
dir
.
exists
());
assertTrue
(
d1
.
exists
());
assertTrue
(
d1f1
.
exists
());
assertFalse
(
d2
.
exists
());
assertFalse
(
d2f2
.
exists
());
assertFalse
(
f1
.
exists
());
}
// Deletes get retried if they fail 1st time around,
// allowing the operation to succeed on subsequent attempts.
// Note: This is what bug JENKINS-15331 is all about.
{
mkdirs
(
dir
,
d1
,
d2
);
touchWithFileName
(
f1
,
d1f1
,
d2f2
);
locker
.
acquireLock
(
d2f2
);
Object
readyToUnlockSignal
=
new
Object
();
Object
readyToDeleteSignal
=
new
Object
();
AtomicBoolean
lockedFileExists
=
new
AtomicBoolean
();
Thread
thread
=
new
Thread
(()
->
{
try
{
readyToUnlockSignal
.
wait
();
locker
.
releaseLock
(
d2f2
);
readyToDeleteSignal
.
notifyAll
();
}
catch
(
Exception
ignored
)
{
}
});
thread
.
start
();
PathRemover
remover
=
PathRemover
.
newRemoverWithStrategy
(
retriesAttempted
->
{
if
(
retriesAttempted
==
0
)
{
lockedFileExists
.
set
(
d2f2
.
exists
());
readyToUnlockSignal
.
notifyAll
();
try
{
readyToDeleteSignal
.
wait
();
return
true
;
}
catch
(
InterruptedException
e
)
{
return
false
;
}
}
return
false
;
});
remover
.
forceRemoveRecursive
(
dir
.
toPath
());
thread
.
join
();
assertTrue
(
lockedFileExists
.
get
());
assertFalse
(
dir
.
exists
());
}
locker
.
acquireLock
(
d1f1
);
PathRemover
remover
=
PathRemover
.
newSimpleRemover
();
expectedException
.
expectMessage
(
containsString
(
dir
.
getPath
()));
remover
.
forceRemoveRecursive
(
dir
.
toPath
());
assertTrue
(
dir
.
exists
());
assertTrue
(
d1
.
exists
());
assertTrue
(
d1f1
.
exists
());
assertFalse
(
d2
.
exists
());
assertFalse
(
d2f2
.
exists
());
assertFalse
(
f1
.
exists
());
}
}
// An interrupt aborts the delete and makes it fail, even
// if we had been told to retry a lot.
{
mkdirs
(
dir
,
d1
,
d2
);
touchWithFileName
(
f1
,
d1f1
,
d2f2
);
locker
.
acquireLock
(
d1f1
);
AtomicReference
<
InterruptedException
>
interrupted
=
new
AtomicReference
<>();
AtomicReference
<
IOException
>
removed
=
new
AtomicReference
<>();
PathRemover
remover
=
PathRemover
.
newRemoverWithStrategy
(
retriesAttempted
->
{
@Test
public
void
testForceRemoveRecursive_RetryOnFailure
()
throws
Exception
{
assumeTrue
(
Functions
.
isWindows
());
File
dir
=
tmp
.
newFolder
();
File
d1
=
new
File
(
dir
,
"d1"
);
File
d2
=
new
File
(
dir
,
"d2"
);
File
f1
=
new
File
(
dir
,
"f1"
);
File
d1f1
=
new
File
(
d1
,
"d1f1"
);
File
d2f2
=
new
File
(
d2
,
"d1f2"
);
mkdirs
(
d1
,
d2
);
touchWithFileName
(
f1
,
d1f1
,
d2f2
);
try
(
FileLocker
locker
=
new
FileLocker
())
{
locker
.
acquireLock
(
d2f2
);
Object
readyToUnlockSignal
=
new
Object
();
Object
readyToDeleteSignal
=
new
Object
();
AtomicBoolean
lockedFileExists
=
new
AtomicBoolean
();
Thread
thread
=
new
Thread
(()
->
{
try
{
readyToUnlockSignal
.
wait
();
locker
.
releaseLock
(
d2f2
);
readyToDeleteSignal
.
notifyAll
();
}
catch
(
Exception
ignored
)
{
}
});
thread
.
start
();
PathRemover
remover
=
PathRemover
.
newRemoverWithStrategy
(
retriesAttempted
->
{
if
(
retriesAttempted
==
0
)
{
lockedFileExists
.
set
(
d2f2
.
exists
());
readyToUnlockSignal
.
notifyAll
();
try
{
TimeUnit
.
SECONDS
.
sleep
(
retriesAttempted
+
1
);
readyToDeleteSignal
.
wait
(
);
return
true
;
}
catch
(
InterruptedException
e
)
{
interrupted
.
set
(
e
);
return
false
;
}
});
Thread
thread
=
new
Thread
(()
->
{
try
{
remover
.
forceRemoveRecursive
(
dir
.
toPath
());
}
catch
(
IOException
e
)
{
removed
.
set
(
e
);
}
});
thread
.
start
();
TimeUnit
.
MILLISECONDS
.
sleep
(
100
);
thread
.
interrupt
();
thread
.
join
();
assertFalse
(
thread
.
isAlive
());
assertTrue
(
d1f1
.
exists
());
IOException
ioException
=
removed
.
get
();
assertNotNull
(
ioException
);
assertThat
(
ioException
.
getMessage
(),
containsString
(
dir
.
getPath
()));
assertNotNull
(
interrupted
.
get
());
}
}
return
false
;
});
remover
.
forceRemoveRecursive
(
dir
.
toPath
());
thread
.
join
();
assertTrue
(
lockedFileExists
.
get
());
assertFalse
(
dir
.
exists
());
}
}
@Test
public
void
testForceRemoveRecursive_FailsWhenInterrupted
()
throws
Exception
{
assumeTrue
(
Functions
.
isWindows
());
File
dir
=
tmp
.
newFolder
();
File
d1
=
new
File
(
dir
,
"d1"
);
File
d2
=
new
File
(
dir
,
"d2"
);
File
f1
=
new
File
(
dir
,
"f1"
);
File
d1f1
=
new
File
(
d1
,
"d1f1"
);
File
d2f2
=
new
File
(
d2
,
"d1f2"
);
mkdirs
(
d1
,
d2
);
touchWithFileName
(
f1
,
d1f1
,
d2f2
);
try
(
FileLocker
locker
=
new
FileLocker
())
{
locker
.
acquireLock
(
d1f1
);
AtomicReference
<
InterruptedException
>
interrupted
=
new
AtomicReference
<>();
AtomicReference
<
IOException
>
removed
=
new
AtomicReference
<>();
PathRemover
remover
=
PathRemover
.
newRemoverWithStrategy
(
retriesAttempted
->
{
try
{
TimeUnit
.
SECONDS
.
sleep
(
retriesAttempted
+
1
);
return
true
;
}
catch
(
InterruptedException
e
)
{
interrupted
.
set
(
e
);
return
false
;
}
});
Thread
thread
=
new
Thread
(()
->
{
try
{
remover
.
forceRemoveRecursive
(
dir
.
toPath
());
}
catch
(
IOException
e
)
{
removed
.
set
(
e
);
}
});
thread
.
start
();
TimeUnit
.
MILLISECONDS
.
sleep
(
100
);
thread
.
interrupt
();
thread
.
join
();
assertFalse
(
thread
.
isAlive
());
assertTrue
(
d1f1
.
exists
());
IOException
ioException
=
removed
.
get
();
assertNotNull
(
ioException
);
assertThat
(
ioException
.
getMessage
(),
containsString
(
dir
.
getPath
()));
assertNotNull
(
interrupted
.
get
());
}
}
private
static
void
mkdirs
(
File
...
dirs
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录