// Copyright 2015 The Bazel Authors. All rights reserved. // // 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.google.devtools.build.lib.analysis.actions; import static com.google.common.truth.Truth.assertThat; import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.NULL_ACTION_OWNER; import com.google.devtools.build.lib.actions.ActionOwner; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.ConfiguredTarget; import com.google.devtools.build.lib.analysis.RuleContext; import com.google.devtools.build.lib.util.LazyString; import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public class FileWriteActionTest extends FileWriteActionTestCase { @Override protected FileWriteAction createAction( ActionOwner actionOwner, Artifact outputArtifact, String data, boolean makeExecutable) { return FileWriteAction.create( actionOwner, outputArtifact, data, makeExecutable, FileWriteAction.Compression.DISALLOW); } @Test public void testNoInputs() { checkNoInputsByDefault(); } @Test public void testDestinationArtifactIsOutput() { checkDestinationArtifactIsOutput(); } @Test public void testCanWriteNonExecutableFile() throws Exception { checkCanWriteNonExecutableFile(); } @Test public void testCanWriteExecutableFile() throws Exception { checkCanWriteExecutableFile(); } @Test public void testComputesConsistentKeys() throws Exception { checkComputesConsistentKeys(); } @Test public void testFileWriteActionWithShortString() throws Exception { Artifact outputArtifact = getBinArtifactWithNoOwner("destination.txt"); String contents = "Hello world"; FileWriteAction action = FileWriteAction.create( NULL_ACTION_OWNER, outputArtifact, contents, /*makeExecutable=*/ false, FileWriteAction.Compression.DISALLOW); assertThat(action.getFileContents()).isEqualTo(contents); } @Test public void testFileWriteActionWithLazyString() throws Exception { Artifact outputArtifact = getBinArtifactWithNoOwner("destination.txt"); final String backingString = "Hello world"; LazyString contents = new LazyString() { @Override public String toString() { return backingString; } }; FileWriteAction action = FileWriteAction.create( NULL_ACTION_OWNER, outputArtifact, contents, /*makeExecutable=*/ false, FileWriteAction.Compression.DISALLOW); assertThat(action.getFileContents()).isEqualTo(backingString); } /** * Returns a string filled with (deterministic) random characters to get a string that won't * compress to a tiny size. */ private String generateLongRandomString() { StringBuilder sb = new StringBuilder(); Random random = new Random(0); for (int i = 0; i < 16 * 1024; ++i) { char c = (char) random.nextInt(128); sb.append(c); } return sb.toString(); } @Test public void testFileWriteActionWithLongStringAndCompression() throws Exception { Artifact outputArtifact = getBinArtifactWithNoOwner("destination.txt"); String contents = generateLongRandomString(); FileWriteAction action = FileWriteAction.create( NULL_ACTION_OWNER, outputArtifact, contents, /*makeExecutable=*/ false, FileWriteAction.Compression.ALLOW); assertThat(action.getFileContents()).isEqualTo(contents); } @Test public void testFileWriteActionWithCompressionDoesNotForceLazyString() throws Exception { Artifact outputArtifact = getBinArtifactWithNoOwner("destination.txt"); final String backingContents = generateLongRandomString(); class ForceCountingLazyString extends LazyString { public int forced = 0; @Override public String toString() { forced += 1; return backingContents; } } ForceCountingLazyString contents = new ForceCountingLazyString(); FileWriteAction action = FileWriteAction.create( NULL_ACTION_OWNER, outputArtifact, contents, /*makeExecutable=*/ false, FileWriteAction.Compression.ALLOW); // The string should only be forced once we actually read it, not when the action is // constructed. assertThat(contents.forced).isEqualTo(0); assertThat(action.getFileContents()).isEqualTo(backingContents); assertThat(contents.forced).isEqualTo(1); } @Test public void testTransparentCompressionFlagOn() throws Exception { Artifact outputArtifact = getBinArtifactWithNoOwner("destination.txt"); String contents = generateLongRandomString(); useConfiguration("--experimental_transparent_compression=true"); ConfiguredTarget target = scratchConfiguredTarget("a", "a", "filegroup(name='a', srcs=[])"); RuleContext context = getRuleContext(target); FileWriteAction action = FileWriteAction.create(context, outputArtifact, contents, /*makeExecutable=*/ false); assertThat(action.usesCompression()).isTrue(); } @Test public void testTransparentCompressionFlagOff() throws Exception { Artifact outputArtifact = getBinArtifactWithNoOwner("destination.txt"); String contents = generateLongRandomString(); useConfiguration("--experimental_transparent_compression=false"); ConfiguredTarget target = scratchConfiguredTarget("a", "a", "filegroup(name='a', srcs=[])"); RuleContext context = getRuleContext(target); FileWriteAction action = FileWriteAction.create(context, outputArtifact, contents, /*makeExecutable=*/ false); assertThat(action.usesCompression()).isFalse(); } }