/* * 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.rules; import static org.junit.Assert.assertThat; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.testutil.FakeFileHashCache; import com.facebook.buck.testutil.FakeProjectFilesystem; import com.facebook.buck.util.cache.FileHashCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.hash.HashCode; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.Optional; import org.hamcrest.Matchers; import org.junit.Test; public class ManifestTest { private static final SourcePathResolver RESOLVER = new SourcePathResolver( new SourcePathRuleFinder( new BuildRuleResolver( TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()))); @Test public void toMap() { ImmutableMap<RuleKey, ImmutableMap<String, HashCode>> entries = ImmutableMap.of(new RuleKey("aa"), ImmutableMap.of("foo/bar.h", HashCode.fromInt(20))); assertThat(Manifest.fromMap(new RuleKey("cc"), entries).toMap(), Matchers.equalTo(entries)); } @Test public void emptyManifest() { assertThat(new Manifest(new RuleKey("cc")).toMap().entrySet(), Matchers.empty()); } @Test public void serialize() throws IOException { ImmutableMap<RuleKey, ImmutableMap<String, HashCode>> entries = ImmutableMap.of(new RuleKey("aa"), ImmutableMap.of("foo/bar.h", HashCode.fromInt(20))); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); Manifest.fromMap(new RuleKey("cc"), entries).serialize(byteArrayOutputStream); Manifest deserialized = new Manifest(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); assertThat(deserialized.toMap(), Matchers.equalTo(entries)); } @Test public void addEntry() throws IOException { Manifest manifest = new Manifest(new RuleKey("cc")); RuleKey key = new RuleKey("aa"); SourcePath input = new FakeSourcePath("input.h"); HashCode hashCode = HashCode.fromInt(20); FileHashCache fileHashCache = new FakeFileHashCache(ImmutableMap.of(RESOLVER.getAbsolutePath(input), hashCode)); manifest.addEntry(fileHashCache, key, RESOLVER, ImmutableSet.of(input), ImmutableSet.of(input)); assertThat( manifest.toMap(), Matchers.equalTo( ImmutableMap.of( key, ImmutableMap.of(RESOLVER.getRelativePath(input).toString(), hashCode)))); } @Test public void addEntryFromArchive() throws IOException { Manifest manifest = new Manifest(new RuleKey("cc")); RuleKey key = new RuleKey("aa"); SourcePath input = ArchiveMemberSourcePath.of( new FakeSourcePath("somewhere/a.jar"), Paths.get("Member.class")); HashCode hashCode = HashCode.fromInt(20); FileHashCache fileHashCache = new FakeFileHashCache( new HashMap<>(), ImmutableMap.of(RESOLVER.getAbsoluteArchiveMemberPath(input), hashCode), new HashMap<>()); manifest.addEntry(fileHashCache, key, RESOLVER, ImmutableSet.of(input), ImmutableSet.of(input)); assertThat( manifest.toMap(), Matchers.equalTo( ImmutableMap.of( key, ImmutableMap.of( RESOLVER.getRelativeArchiveMemberPath(input).toString(), hashCode)))); } @Test public void addEntryWithSourcePathsThatHaveSameRelativePaths() throws IOException { RuleKey key = new RuleKey("aa"); Path tmp1 = Files.createTempDirectory("tmp1"); ProjectFilesystem filesystem1 = new FakeProjectFilesystem(tmp1); SourcePath input1 = new PathSourcePath(filesystem1, Paths.get("input.h")); HashCode hashCode1 = HashCode.fromInt(1); Path tmp2 = Files.createTempDirectory("tmp2"); ProjectFilesystem filesystem2 = new FakeProjectFilesystem(tmp2); SourcePath input2 = new PathSourcePath(filesystem2, Paths.get("input.h")); HashCode hashCode2 = HashCode.fromInt(1); FileHashCache fileHashCache = new FakeFileHashCache( ImmutableMap.of( RESOLVER.getAbsolutePath(input1), hashCode1, RESOLVER.getAbsolutePath(input2), hashCode2)); Manifest manifest1 = new Manifest(new RuleKey("cc")); manifest1.addEntry( fileHashCache, key, RESOLVER, ImmutableSet.of(input1, input2), ImmutableSet.of(input1)); assertThat( manifest1.toMap(), Matchers.equalTo( ImmutableMap.of( key, ImmutableMap.of( RESOLVER.getRelativePath(input1).toString(), Manifest.hashSourcePathGroup( fileHashCache, RESOLVER, ImmutableList.of(input1, input2)))))); Manifest manifest2 = new Manifest(new RuleKey("cc")); manifest2.addEntry( fileHashCache, key, RESOLVER, ImmutableSet.of(input1, input2), ImmutableSet.of(input2)); assertThat( manifest2.toMap(), Matchers.equalTo( ImmutableMap.of( key, ImmutableMap.of( RESOLVER.getRelativePath(input2).toString(), Manifest.hashSourcePathGroup( fileHashCache, RESOLVER, ImmutableList.of(input1, input2)))))); } @Test public void lookupMatch() throws IOException { RuleKey key = new RuleKey("aa"); SourcePath input = new FakeSourcePath("input.h"); HashCode hashCode = HashCode.fromInt(20); Manifest manifest = Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( key, ImmutableMap.of(RESOLVER.getRelativePath(input).toString(), hashCode))); FileHashCache fileHashCache = new FakeFileHashCache(ImmutableMap.of(RESOLVER.getAbsolutePath(input), hashCode)); assertThat( manifest.lookup(fileHashCache, RESOLVER, ImmutableSet.of(input)), Matchers.equalTo(Optional.of(key))); } @Test public void lookupMatchWithSourcePathsThatHaveSameRelativePaths() throws IOException { RuleKey key = new RuleKey("aa"); Path tmp1 = Files.createTempDirectory("tmp1"); ProjectFilesystem filesystem1 = new FakeProjectFilesystem(tmp1); SourcePath input1 = new PathSourcePath(filesystem1, Paths.get("input.h")); HashCode hashCode1 = HashCode.fromInt(1); Path tmp2 = Files.createTempDirectory("tmp2"); ProjectFilesystem filesystem2 = new FakeProjectFilesystem(tmp2); SourcePath input2 = new PathSourcePath(filesystem2, Paths.get("input.h")); HashCode hashCode2 = HashCode.fromInt(1); FileHashCache fileHashCache = new FakeFileHashCache( ImmutableMap.of( RESOLVER.getAbsolutePath(input1), hashCode1, RESOLVER.getAbsolutePath(input2), hashCode2)); Manifest manifest1 = Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( key, ImmutableMap.of( RESOLVER.getRelativePath(input1).toString(), Manifest.hashSourcePathGroup( fileHashCache, RESOLVER, ImmutableList.of(input1, input2))))); assertThat( manifest1.lookup(fileHashCache, RESOLVER, ImmutableSet.of(input1, input2)), Matchers.equalTo(Optional.of(key))); Manifest manifest2 = Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( key, ImmutableMap.of( RESOLVER.getRelativePath(input2).toString(), Manifest.hashSourcePathGroup( fileHashCache, RESOLVER, ImmutableList.of(input1, input2))))); assertThat( manifest2.lookup(fileHashCache, RESOLVER, ImmutableSet.of(input1, input2)), Matchers.equalTo(Optional.of(key))); } @Test public void lookupHashMismatch() throws IOException { RuleKey key = new RuleKey("aa"); SourcePath input = new FakeSourcePath("input.h"); Manifest manifest = Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( key, ImmutableMap.of(RESOLVER.getRelativePath(input).toString(), HashCode.fromInt(1)))); FileHashCache fileHashCache = new FakeFileHashCache( ImmutableMap.of(RESOLVER.getAbsolutePath(input), HashCode.fromInt(2))); assertThat( manifest.lookup(fileHashCache, RESOLVER, ImmutableSet.of(input)), Matchers.equalTo(Optional.empty())); } @Test public void lookupMissingHeader() throws IOException { RuleKey key = new RuleKey("aa"); SourcePath input = new FakeSourcePath("input.h"); Manifest manifest = Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( key, ImmutableMap.of(RESOLVER.getRelativePath(input).toString(), HashCode.fromInt(1)))); FileHashCache fileHashCache = new FakeFileHashCache(ImmutableMap.of()); assertThat( manifest.lookup(fileHashCache, RESOLVER, ImmutableSet.of(input)), Matchers.equalTo(Optional.empty())); } @Test public void lookupMatchAfterHashMismatch() throws IOException { RuleKey key1 = new RuleKey("aa"); RuleKey key2 = new RuleKey("bb"); SourcePath input = new FakeSourcePath("input.h"); Manifest manifest = Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( key1, ImmutableMap.of(RESOLVER.getRelativePath(input).toString(), HashCode.fromInt(1)), key2, ImmutableMap.of(RESOLVER.getRelativePath(input).toString(), HashCode.fromInt(2)))); FileHashCache fileHashCache = new FakeFileHashCache( ImmutableMap.of(RESOLVER.getAbsolutePath(input), HashCode.fromInt(2))); assertThat( manifest.lookup(fileHashCache, RESOLVER, ImmutableSet.of(input)), Matchers.equalTo(Optional.of(key2))); } @Test public void size() { assertThat(new Manifest(new RuleKey("cc")).size(), Matchers.equalTo(0)); assertThat( Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of(new RuleKey("aa"), ImmutableMap.of("foo.h", HashCode.fromInt(0)))) .size(), Matchers.equalTo(1)); assertThat( Manifest.fromMap( new RuleKey("cc"), ImmutableMap.of( new RuleKey("aa"), ImmutableMap.of("foo.h", HashCode.fromInt(0)), new RuleKey("bb"), ImmutableMap.of("bar.h", HashCode.fromInt(0)))) .size(), Matchers.equalTo(2)); } }