Home | History | Annotate | Download | only in util
      1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #include "tensorflow/core/util/events_writer.h"
     17 
     18 #include <math.h>
     19 #include "tensorflow/core/framework/summary.pb.h"
     20 #include "tensorflow/core/lib/core/errors.h"
     21 #include "tensorflow/core/lib/core/status.h"
     22 #include "tensorflow/core/lib/core/status_test_util.h"
     23 #include "tensorflow/core/lib/io/path.h"
     24 #include "tensorflow/core/lib/io/record_reader.h"
     25 #include "tensorflow/core/lib/strings/strcat.h"
     26 #include "tensorflow/core/platform/env.h"
     27 #include "tensorflow/core/platform/logging.h"
     28 #include "tensorflow/core/platform/protobuf.h"
     29 #include "tensorflow/core/platform/test.h"
     30 #include "tensorflow/core/util/event.pb.h"
     31 
     32 namespace tensorflow {
     33 namespace {
     34 
     35 // shorthand
     36 Env* env() { return Env::Default(); }
     37 
     38 void WriteSimpleValue(EventsWriter* writer, double wall_time, int64 step,
     39                       const string& tag, float simple_value) {
     40   Event event;
     41   event.set_wall_time(wall_time);
     42   event.set_step(step);
     43   Summary::Value* summ_val = event.mutable_summary()->add_value();
     44   summ_val->set_tag(tag);
     45   summ_val->set_simple_value(simple_value);
     46   writer->WriteEvent(event);
     47 }
     48 
     49 void WriteFile(EventsWriter* writer) {
     50   WriteSimpleValue(writer, 1234, 34, "foo", 3.14159);
     51   WriteSimpleValue(writer, 2345, 35, "bar", -42);
     52 }
     53 
     54 static bool ReadEventProto(io::RecordReader* reader, uint64* offset,
     55                            Event* proto) {
     56   string record;
     57   Status s = reader->ReadRecord(offset, &record);
     58   if (!s.ok()) {
     59     return false;
     60   }
     61   return ParseProtoUnlimited(proto, record);
     62 }
     63 
     64 void VerifyFile(const string& filename) {
     65   CHECK(env()->FileExists(filename).ok());
     66   std::unique_ptr<RandomAccessFile> event_file;
     67   TF_CHECK_OK(env()->NewRandomAccessFile(filename, &event_file));
     68   io::RecordReader* reader = new io::RecordReader(event_file.get());
     69 
     70   uint64 offset = 0;
     71 
     72   Event actual;
     73   CHECK(ReadEventProto(reader, &offset, &actual));
     74   VLOG(1) << actual.ShortDebugString();
     75   // Wall time should be within 5s of now.
     76 
     77   double current_time = env()->NowMicros() / 1000000.0;
     78   EXPECT_LT(fabs(actual.wall_time() - current_time), 5);
     79   // Should have the current version number.
     80   EXPECT_EQ(actual.file_version(),
     81             strings::StrCat(EventsWriter::kVersionPrefix,
     82                             EventsWriter::kCurrentVersion));
     83 
     84   Event expected;
     85   CHECK(ReadEventProto(reader, &offset, &actual));
     86   VLOG(1) << actual.ShortDebugString();
     87   ASSERT_TRUE(protobuf::TextFormat::ParseFromString(
     88       "wall_time: 1234 step: 34 "
     89       "summary { value { tag: 'foo' simple_value: 3.14159 } }",
     90       &expected));
     91   // TODO(keveman): Enable this check
     92   // EXPECT_THAT(expected, EqualsProto(actual));
     93 
     94   CHECK(ReadEventProto(reader, &offset, &actual));
     95   VLOG(1) << actual.ShortDebugString();
     96   ASSERT_TRUE(protobuf::TextFormat::ParseFromString(
     97       "wall_time: 2345 step: 35 "
     98       "summary { value { tag: 'bar' simple_value: -42 } }",
     99       &expected));
    100   // TODO(keveman): Enable this check
    101   // EXPECT_THAT(expected, EqualsProto(actual));
    102 
    103   TF_CHECK_OK(env()->DeleteFile(filename));
    104   delete reader;
    105 }
    106 
    107 string GetDirName(const string& suffix) {
    108   return io::JoinPath(testing::TmpDir(), suffix);
    109 }
    110 
    111 TEST(EventWriter, WriteFlush) {
    112   string file_prefix = GetDirName("/writeflush_test");
    113   EventsWriter writer(file_prefix);
    114   WriteFile(&writer);
    115   TF_EXPECT_OK(writer.Flush());
    116   string filename = writer.FileName();
    117   VerifyFile(filename);
    118 }
    119 
    120 TEST(EventWriter, WriteClose) {
    121   string file_prefix = GetDirName("/writeclose_test");
    122   EventsWriter writer(file_prefix);
    123   WriteFile(&writer);
    124   TF_EXPECT_OK(writer.Close());
    125   string filename = writer.FileName();
    126   VerifyFile(filename);
    127 }
    128 
    129 TEST(EventWriter, WriteDelete) {
    130   string file_prefix = GetDirName("/writedelete_test");
    131   EventsWriter* writer = new EventsWriter(file_prefix);
    132   WriteFile(writer);
    133   string filename = writer->FileName();
    134   delete writer;
    135   VerifyFile(filename);
    136 }
    137 
    138 TEST(EventWriter, FailFlush) {
    139   string file_prefix = GetDirName("/failflush_test");
    140   EventsWriter writer(file_prefix);
    141   string filename = writer.FileName();
    142   WriteFile(&writer);
    143   TF_EXPECT_OK(env()->FileExists(filename));
    144   TF_ASSERT_OK(env()->DeleteFile(filename));
    145   EXPECT_EQ(errors::Code::NOT_FOUND, env()->FileExists(filename).code());
    146   EXPECT_FALSE(writer.Flush().ok());
    147   EXPECT_EQ(errors::Code::NOT_FOUND, env()->FileExists(filename).code());
    148 }
    149 
    150 TEST(EventWriter, FailClose) {
    151   string file_prefix = GetDirName("/failclose_test");
    152   EventsWriter writer(file_prefix);
    153   string filename = writer.FileName();
    154   WriteFile(&writer);
    155   TF_EXPECT_OK(env()->FileExists(filename));
    156   TF_ASSERT_OK(env()->DeleteFile(filename));
    157   EXPECT_EQ(errors::Code::NOT_FOUND, env()->FileExists(filename).code());
    158   EXPECT_FALSE(writer.Close().ok());
    159   EXPECT_EQ(errors::Code::NOT_FOUND, env()->FileExists(filename).code());
    160 }
    161 
    162 TEST(EventWriter, InitWriteClose) {
    163   string file_prefix = GetDirName("/initwriteclose_test");
    164   EventsWriter writer(file_prefix);
    165   TF_EXPECT_OK(writer.Init());
    166   string filename0 = writer.FileName();
    167   TF_EXPECT_OK(env()->FileExists(filename0));
    168   WriteFile(&writer);
    169   TF_EXPECT_OK(writer.Close());
    170   string filename1 = writer.FileName();
    171   EXPECT_EQ(filename0, filename1);
    172   VerifyFile(filename1);
    173 }
    174 
    175 TEST(EventWriter, NameWriteClose) {
    176   string file_prefix = GetDirName("/namewriteclose_test");
    177   EventsWriter writer(file_prefix);
    178   string filename = writer.FileName();
    179   TF_EXPECT_OK(env()->FileExists(filename));
    180   WriteFile(&writer);
    181   TF_EXPECT_OK(writer.Close());
    182   VerifyFile(filename);
    183 }
    184 
    185 TEST(EventWriter, NameClose) {
    186   string file_prefix = GetDirName("/nameclose_test");
    187   EventsWriter writer(file_prefix);
    188   string filename = writer.FileName();
    189   TF_EXPECT_OK(writer.Close());
    190   TF_EXPECT_OK(env()->FileExists(filename));
    191   TF_ASSERT_OK(env()->DeleteFile(filename));
    192 }
    193 
    194 TEST(EventWriter, FileDeletionBeforeWriting) {
    195   string file_prefix = GetDirName("/fdbw_test");
    196   EventsWriter writer(file_prefix);
    197   string filename0 = writer.FileName();
    198   TF_EXPECT_OK(env()->FileExists(filename0));
    199   env()->SleepForMicroseconds(
    200       2000000);  // To make sure timestamp part of filename will differ.
    201   TF_ASSERT_OK(env()->DeleteFile(filename0));
    202   TF_EXPECT_OK(writer.Init());  // Init should reopen file.
    203   WriteFile(&writer);
    204   TF_EXPECT_OK(writer.Flush());
    205   string filename1 = writer.FileName();
    206   EXPECT_NE(filename0, filename1);
    207   VerifyFile(filename1);
    208 }
    209 
    210 }  // namespace
    211 }  // namespace tensorflow
    212