/*
* Copyright 2015-present Facebook, Inc.
*
* Licensed 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 com.facebook.buck.cxx;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import com.facebook.buck.cli.BuckConfig;
import com.facebook.buck.cli.FakeBuckConfig;
import com.facebook.buck.model.InternalFlavor;
import com.facebook.buck.rules.ConstantToolProvider;
import com.facebook.buck.rules.HashedFileTool;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.util.environment.Platform;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Paths;
import java.util.Optional;
import org.hamcrest.junit.ExpectedException;
import org.junit.Rule;
import org.junit.Test;
/** Unit tests for {@link CxxPlatforms}. */
public class CxxPlatformsTest {
@Rule public final ExpectedException expectedException = ExpectedException.none();
@Test
public void returnsKnownDefaultPlatformSetInConfig() {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of("cxx", ImmutableMap.of("default_platform", "borland_cxx_452"));
CompilerProvider compiler =
new CompilerProvider(Paths.get("borland"), Optional.of(CxxToolProvider.Type.GCC));
PreprocessorProvider preprocessor =
new PreprocessorProvider(Paths.get("borland"), Optional.of(CxxToolProvider.Type.GCC));
CxxPlatform borlandCxx452Platform =
CxxPlatform.builder()
.setFlavor(InternalFlavor.of("borland_cxx_452"))
.setAs(compiler)
.setAspp(preprocessor)
.setCc(compiler)
.setCpp(preprocessor)
.setCxx(compiler)
.setCxxpp(preprocessor)
.setLd(
new DefaultLinkerProvider(
LinkerProvider.Type.GNU,
new ConstantToolProvider(new HashedFileTool(Paths.get("borland")))))
.setStrip(new HashedFileTool(Paths.get("borland")))
.setSymbolNameTool(new PosixNmSymbolNameTool(new HashedFileTool(Paths.get("borland"))))
.setAr(new GnuArchiver(new HashedFileTool(Paths.get("borland"))))
.setRanlib(new HashedFileTool(Paths.get("borland")))
.setSharedLibraryExtension("so")
.setSharedLibraryVersionedExtensionFormat(".so.%s")
.setStaticLibraryExtension("a")
.setObjectFileExtension("so")
.setCompilerDebugPathSanitizer(CxxPlatformUtils.DEFAULT_COMPILER_DEBUG_PATH_SANITIZER)
.setAssemblerDebugPathSanitizer(CxxPlatformUtils.DEFAULT_ASSEMBLER_DEBUG_PATH_SANITIZER)
.setHeaderVerification(CxxPlatformUtils.DEFAULT_PLATFORM.getHeaderVerification())
.setPublicHeadersSymlinksEnabled(true)
.setPrivateHeadersSymlinksEnabled(true)
.build();
BuckConfig buckConfig = FakeBuckConfig.builder().setSections(sections).build();
assertThat(
CxxPlatforms.getConfigDefaultCxxPlatform(
new CxxBuckConfig(buckConfig),
ImmutableMap.of(borlandCxx452Platform.getFlavor(), borlandCxx452Platform),
CxxPlatformUtils.DEFAULT_PLATFORM),
equalTo(borlandCxx452Platform));
}
@Test
public void unknownDefaultPlatformSetInConfigFallsBackToSystemDefault() {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of("cxx", ImmutableMap.of("default_platform", "borland_cxx_452"));
BuckConfig buckConfig = FakeBuckConfig.builder().setSections(sections).build();
assertThat(
CxxPlatforms.getConfigDefaultCxxPlatform(
new CxxBuckConfig(buckConfig), ImmutableMap.of(), CxxPlatformUtils.DEFAULT_PLATFORM),
equalTo(CxxPlatformUtils.DEFAULT_PLATFORM));
}
@Test
public void compilerOnlyFlagsNotAddedToPreprocessor() {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of(
"cxx",
ImmutableMap.of(
"compiler_only_flags", "-Wtest",
"cppflags", "-Wp",
"cxxppflags", "-Wxp"));
CxxBuckConfig buckConfig =
new CxxBuckConfig(FakeBuckConfig.builder().setSections(sections).build());
CxxPlatform platform = CxxPlatformUtils.build(buckConfig);
assertThat(platform.getCflags(), hasItem("-Wtest"));
assertThat(platform.getCxxflags(), hasItem("-Wtest"));
assertThat(platform.getCppflags(), hasItem("-Wp"));
assertThat(platform.getCppflags(), not(hasItem("-Wtest")));
assertThat(platform.getCxxppflags(), hasItem("-Wxp"));
assertThat(platform.getCxxppflags(), not(hasItem("-Wtest")));
}
public LinkerProvider getPlatformLinker(LinkerProvider.Type linkerType) {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of(
"cxx",
ImmutableMap.of(
"ld", Paths.get("fake_path").toString(),
"linker_platform", linkerType.name()));
CxxBuckConfig buckConfig =
new CxxBuckConfig(
FakeBuckConfig.builder()
.setSections(sections)
.setFilesystem(new FakeProjectFilesystem(ImmutableSet.of(Paths.get("fake_path"))))
.build());
return CxxPlatformUtils.build(buckConfig).getLd();
}
@Test
public void linkerOverriddenByConfig() {
assertThat(
"MACOS linker was not a DarwinLinker instance",
getPlatformLinker(LinkerProvider.Type.DARWIN).getType(),
is(LinkerProvider.Type.DARWIN));
assertThat(
"LINUX linker was not a GnuLinker instance",
getPlatformLinker(LinkerProvider.Type.GNU).getType(),
is(LinkerProvider.Type.GNU));
assertThat(
"WINDOWS linker was not a GnuLinker instance",
getPlatformLinker(LinkerProvider.Type.WINDOWS).getType(),
is(LinkerProvider.Type.WINDOWS));
}
@Test
public void invalidLinkerOverrideFails() {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of(
"cxx",
ImmutableMap.of(
"ld", Paths.get("fake_path").toString(), "linker_platform", "WRONG_PLATFORM"));
CxxBuckConfig buckConfig =
new CxxBuckConfig(
FakeBuckConfig.builder()
.setSections(sections)
.setFilesystem(new FakeProjectFilesystem(ImmutableSet.of(Paths.get("fake_path"))))
.build());
expectedException.expect(RuntimeException.class);
CxxPlatformUtils.build(buckConfig);
}
public Archiver getPlatformArchiver(Platform archiverPlatform) {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of(
"cxx",
ImmutableMap.of(
"ar", Paths.get("fake_path").toString(),
"archiver_platform", archiverPlatform.name()));
CxxBuckConfig buckConfig =
new CxxBuckConfig(
FakeBuckConfig.builder()
.setSections(sections)
.setFilesystem(new FakeProjectFilesystem(ImmutableSet.of(Paths.get("fake_path"))))
.build());
Archiver archiver = CxxPlatformUtils.build(buckConfig).getAr();
if (archiver instanceof LazyDelegatingArchiver) {
return ((LazyDelegatingArchiver) archiver).getDelegate();
} else {
return archiver;
}
}
@Test
public void archiverrOverriddenByConfig() {
assertThat(
"MACOS archiver was not a BsdArchiver instance",
getPlatformArchiver(Platform.MACOS),
instanceOf(BsdArchiver.class));
assertThat(
"LINUX archiver was not a GnuArchiver instance",
getPlatformArchiver(Platform.LINUX),
instanceOf(GnuArchiver.class));
assertThat(
"WINDOWS archiver was not a GnuArchiver instance",
getPlatformArchiver(Platform.WINDOWS),
instanceOf(WindowsArchiver.class));
}
@Test
public void invalidArchiverOverrideFails() {
ImmutableMap<String, ImmutableMap<String, String>> sections =
ImmutableMap.of(
"cxx",
ImmutableMap.of(
"ar", Paths.get("fake_path").toString(), "archiver_platform", "WRONG_PLATFORM"));
CxxBuckConfig buckConfig =
new CxxBuckConfig(
FakeBuckConfig.builder()
.setSections(sections)
.setFilesystem(new FakeProjectFilesystem(ImmutableSet.of(Paths.get("fake_path"))))
.build());
expectedException.expect(RuntimeException.class);
((LazyDelegatingArchiver) CxxPlatformUtils.build(buckConfig).getAr()).getDelegate();
}
}