/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.bootstrap;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.lucene.util.Constants;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.MockLogAppender;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.function.Predicate;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class MaxMapCountCheckTests extends ESTestCase {
public void testGetMaxMapCountOnLinux() {
if (Constants.LINUX) {
final BootstrapChecks.MaxMapCountCheck check = new BootstrapChecks.MaxMapCountCheck();
assertThat(check.getMaxMapCount(), greaterThan(0L));
}
}
public void testGetMaxMapCount() throws IOException, IllegalAccessException {
final long procSysVmMaxMapCount = randomIntBetween(1, Integer.MAX_VALUE);
final BufferedReader reader = mock(BufferedReader.class);
when(reader.readLine()).thenReturn(Long.toString(procSysVmMaxMapCount));
final Path procSysVmMaxMapCountPath = PathUtils.get("/proc/sys/vm/max_map_count");
BootstrapChecks.MaxMapCountCheck check = new BootstrapChecks.MaxMapCountCheck() {
@Override
BufferedReader getBufferedReader(Path path) throws IOException {
assertEquals(path, procSysVmMaxMapCountPath);
return reader;
}
};
assertThat(check.getMaxMapCount(), equalTo(procSysVmMaxMapCount));
verify(reader).close();
{
reset(reader);
final IOException ioException = new IOException("fatal");
when(reader.readLine()).thenThrow(ioException);
final Logger logger = ESLoggerFactory.getLogger("testGetMaxMapCountIOException");
final MockLogAppender appender = new MockLogAppender();
appender.start();
appender.addExpectation(
new ParameterizedMessageLoggingExpectation(
"expected logged I/O exception",
"testGetMaxMapCountIOException",
Level.WARN,
"I/O exception while trying to read [{}]",
new Object[] { procSysVmMaxMapCountPath },
e -> ioException == e));
Loggers.addAppender(logger, appender);
assertThat(check.getMaxMapCount(logger), equalTo(-1L));
appender.assertAllExpectationsMatched();
verify(reader).close();
Loggers.removeAppender(logger, appender);
appender.stop();
}
{
reset(reader);
when(reader.readLine()).thenReturn("eof");
final Logger logger = ESLoggerFactory.getLogger("testGetMaxMapCountNumberFormatException");
final MockLogAppender appender = new MockLogAppender();
appender.start();
appender.addExpectation(
new ParameterizedMessageLoggingExpectation(
"expected logged number format exception",
"testGetMaxMapCountNumberFormatException",
Level.WARN,
"unable to parse vm.max_map_count [{}]",
new Object[] { "eof" },
e -> e instanceof NumberFormatException && e.getMessage().equals("For input string: \"eof\"")));
Loggers.addAppender(logger, appender);
assertThat(check.getMaxMapCount(logger), equalTo(-1L));
appender.assertAllExpectationsMatched();
verify(reader).close();
Loggers.removeAppender(logger, appender);
appender.stop();
}
}
private static class ParameterizedMessageLoggingExpectation implements MockLogAppender.LoggingExpectation {
private boolean saw = false;
private final String name;
private final String loggerName;
private final Level level;
private final String messagePattern;
private final Object[] arguments;
private final Predicate<Throwable> throwablePredicate;
private ParameterizedMessageLoggingExpectation(
final String name,
final String loggerName,
final Level level,
final String messagePattern,
final Object[] arguments,
final Predicate<Throwable> throwablePredicate) {
this.name = name;
this.loggerName = loggerName;
this.level = level;
this.messagePattern = messagePattern;
this.arguments = arguments;
this.throwablePredicate = throwablePredicate;
}
@Override
public void match(LogEvent event) {
if (event.getLevel().equals(level) &&
event.getLoggerName().equals(loggerName) &&
event.getMessage() instanceof ParameterizedMessage) {
final ParameterizedMessage message = (ParameterizedMessage)event.getMessage();
saw = message.getFormat().equals(messagePattern) &&
Arrays.deepEquals(arguments, message.getParameters()) &&
throwablePredicate.test(event.getThrown());
}
}
@Override
public void assertMatched() {
assertTrue(name, saw);
}
}
public void testMaxMapCountCheckRead() throws IOException {
final String rawProcSysVmMaxMapCount = Long.toString(randomIntBetween(1, Integer.MAX_VALUE));
final BufferedReader reader = mock(BufferedReader.class);
when(reader.readLine()).thenReturn(rawProcSysVmMaxMapCount);
final BootstrapChecks.MaxMapCountCheck check = new BootstrapChecks.MaxMapCountCheck();
assertThat(check.readProcSysVmMaxMapCount(reader), equalTo(rawProcSysVmMaxMapCount));
}
public void testMaxMapCountCheckParse() {
final long procSysVmMaxMapCount = randomIntBetween(1, Integer.MAX_VALUE);
final BootstrapChecks.MaxMapCountCheck check = new BootstrapChecks.MaxMapCountCheck();
assertThat(check.parseProcSysVmMaxMapCount(Long.toString(procSysVmMaxMapCount)), equalTo(procSysVmMaxMapCount));
}
}